diff --git a/DEPS b/DEPS
index ed929ad..b018594c 100644
--- a/DEPS
+++ b/DEPS
@@ -181,11 +181,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': '6791ee2f8059c6b395e116011fb8e68621cebe6c',
+  'skia_revision': '6dbd7ff34a496f362163e3f082e3d4cb357808b2',
   # 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': '2de68515d603bebe3a3048fd3c34db3c48e0e958',
+  'v8_revision': '1ca8124e52e346c6905b3d086a995c981dc16bc0',
   # 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.
@@ -193,11 +193,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '1031d2c65b5ea85a77013fe6fa17ec9d93e5ca22',
+  'angle_revision': '3311ef65680e5c69e2ea9913eb244b67c2189d91',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '10a900e5ffaffdffe2806b1507af43a74acdfe9e',
+  'swiftshader_revision': '19b43a602225c5c1743c0576280b6c577deee949',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -232,7 +232,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '10d8de7541ab1f26f6f04b2118d13a92a7119102',
+  'freetype_revision': '50b013871c53f7624b5351dd4820a137303fe14b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
@@ -244,7 +244,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'd3a10a0399c14a92d5ffb737c303a03fbfccb98e',
+  'catapult_revision': '2478e62054cf81b2bb2981e3d4b03daab112e789',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -252,7 +252,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': 'eb7e7731ed988e0e6d73610b547395b1f6fba3e3',
+  'devtools_frontend_revision': '77e01616ea7b9584005bcd1424f725713c875740',
   # 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.
@@ -875,7 +875,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '15e191fdcca264f9a89534f1c7f7c2ca6a7e8766',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '024c350baa0372ea748033c91f8098bf3d45ee49',
       'condition': 'checkout_linux',
   },
 
@@ -900,7 +900,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cf50f77484421e2b2f2b8f08c740c7055febac8b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ed0cc5f6fd8ee57e9219f840d492de3109ba6d83',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -959,7 +959,7 @@
   },
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '6334d594f68c2ba36e3e9bf91aac185ac3875717',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '40801e31ed0cd8501c5daa0fe56e4e825165cc9e',
 
   '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'),
@@ -1293,7 +1293,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ad5473a1bad80aa5b6287f97f967e75d787512b0',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '804ad6f18ad8e45dd7f268ec1a9a58580dbc9521',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1494,7 +1494,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '53655df4cde60b121fc530842ba9a6d5dfec1ae1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f3aa6326b8e21f627b9fba72040122723251999b',
+    Var('webrtc_git') + '/src.git' + '@' + 'cfe75c12ee04d17e7898ebc0a8ad1051b6627e53',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1564,7 +1564,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c7797980325fb0e94713d95dd1772b73d9fd1327',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3a46886a357c7e9a64f0b65ba0dfcebb079eb035',
     'condition': 'checkout_src_internal',
   },
 
@@ -1580,7 +1580,7 @@
   },
 
   # === ANDROID_DEPS Generated Code Start ===
-  # Generated by //tools/android/roll/android_deps/fetch_all.py
+  # Generated by //third_party/android_deps/fetch_all.py
   'src/third_party/android_deps/libs/android_arch_core_common': {
       'packages': [
           {
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index d6c17487..89d02e3 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -54,6 +54,32 @@
     }
   }
 
+  if (android_64bit_target_cpu) {
+    # These targets builds a 32-bit only Webview on a 64-bit config, analogous
+    # to what's built on a 32-bit config. This lets all Webviews build on a
+    # single configuration.
+    standalone_system_webview_apk_tmpl("system_webview_32_apk") {
+      apk_name = "SystemWebView32"
+      include_64_bit_webview = false
+    }
+
+    if (enable_webview_bundles) {
+      standalone_system_webview_apk_tmpl(
+          "system_webview_32_base_bundle_module") {
+        target_type = "android_app_bundle_module"
+        include_64_bit_webview = false
+        is_base_module = true
+      }
+
+      system_webview_bundle("system_webview_32_bundle") {
+        base_module_target = ":system_webview_32_base_bundle_module"
+        bundle_name = "SystemWebView32"
+        include_64_bit_webview = false
+        min_sdk_version = 21
+      }
+    }
+  }
+
   android_resource_sizes_test("resource_sizes_system_webview_apk") {
     apk_name = "SystemWebView"
     data_deps = [
@@ -143,6 +169,43 @@
         static_library_provider = "//chrome/android:trichrome_library_64_32_apk"
       }
     }
+
+    template("trichrome_webview_32_tmpl") {
+      system_webview_apk_or_module_tmpl(target_name) {
+        forward_variables_from(invoker, "*")
+        android_manifest = trichrome_webview_32_android_manifest
+        android_manifest_dep =
+            "//android_webview/nonembedded:trichrome_webview_32_manifest"
+        use_trichrome_library = true
+        is_64_bit_browser = false
+        include_64_bit_webview = false
+
+        min_sdk_version = 29
+
+        deps = upstream_only_webview_deps
+        static_library_provider = "//chrome/android:trichrome_library_32_apk"
+      }
+    }
+
+    trichrome_webview_32_tmpl("trichrome_webview_32_apk") {
+      apk_name = "TrichromeWebView32"
+      uncompress_dex = true
+    }
+
+    if (enable_webview_bundles) {
+      trichrome_webview_32_tmpl("trichrome_webview_32_base_bundle_module") {
+        target_type = "android_app_bundle_module"
+        is_base_module = true
+      }
+
+      system_webview_bundle("trichrome_webview_32_bundle") {
+        base_module_target = ":trichrome_webview_32_base_bundle_module"
+        bundle_name = "TrichromeWebView32"
+        uncompress_dex = true
+        min_sdk_version = 29
+        static_library_provider = "//chrome/android:trichrome_library_32_apk"
+      }
+    }
   }
 }
 
@@ -294,9 +357,6 @@
     "java/src/org/chromium/android_webview/AutofillActionModeCallback.java",
     "java/src/org/chromium/android_webview/AwActionModeCallback.java",
     "java/src/org/chromium/android_webview/AwAutofillClient.java",
-    "java/src/org/chromium/android_webview/AwAutofillManager.java",
-    "java/src/org/chromium/android_webview/AwAutofillProvider.java",
-    "java/src/org/chromium/android_webview/AwAutofillUMA.java",
     "java/src/org/chromium/android_webview/AwBrowserContext.java",
     "java/src/org/chromium/android_webview/AwBrowserProcess.java",
     "java/src/org/chromium/android_webview/AwConsoleMessage.java",
@@ -671,9 +731,19 @@
   }
 }
 
-# These assets are needed by both monochrome and stand alone WebView, but not by
-# Chrome or TrichromeWebView.
-android_assets("monochrome_webview_assets") {
+android_assets("webview_primary_abi_assets") {
+  if (use_v8_context_snapshot) {
+    deps = [
+      "//tools/v8_context_snapshot:v8_context_snapshot_assets",
+    ]
+  } else {
+    deps = [
+      "//v8:v8_external_startup_data_assets",
+    ]
+  }
+}
+
+android_assets("monochrome_webview_primary_abi_assets") {
   deps = [
     "//third_party/icu:icu_assets",
   ]
@@ -682,11 +752,33 @@
   } else {
     deps += [ "//v8:v8_external_startup_data_assets" ]
   }
-  if (android_64bit_target_cpu) {
+}
+
+if (android_64bit_target_cpu) {
+  android_assets("webview_secondary_abi_assets") {
+    deps = [
+      ":v8_snapshot_secondary_abi_assets",
+    ]
+  }
+
+  android_assets("monochrome_webview_secondary_abi_assets") {
+    deps = [
+      "//third_party/icu:icu_assets",
+    ]
     deps += [ ":v8_snapshot_secondary_abi_assets" ]
   }
 }
 
+android_assets("weblayer_webview_assets") {
+  deps = [
+    ":webview_primary_abi_assets",
+    "//third_party/icu:icu_assets",
+  ]
+  if (android_64bit_target_cpu) {
+    deps += [ ":webview_secondary_abi_assets" ]
+  }
+}
+
 android_assets("stub_assets") {
   renaming_sources = [ "$root_gen_dir/components/resources/about_credits.html" ]
   renaming_destinations = [ "webview_licenses.notice" ]
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
index e25b008..0761e49 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -30,7 +30,6 @@
 
 import com.android.webview.chromium.WebViewDelegateFactory.WebViewDelegate;
 
-import org.chromium.android_webview.AwAutofillProvider;
 import org.chromium.android_webview.AwBrowserContext;
 import org.chromium.android_webview.AwBrowserProcess;
 import org.chromium.android_webview.AwSettings;
@@ -52,6 +51,7 @@
 import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
 import org.chromium.components.autofill.AutofillProvider;
+import org.chromium.components.autofill.AutofillProviderImpl;
 import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
 import org.chromium.content_public.browser.LGEmailActionModeWorkaround;
 
@@ -577,7 +577,7 @@
 
     AutofillProvider createAutofillProvider(Context context, ViewGroup containerView) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return null;
-        return new AwAutofillProvider(context, containerView);
+        return new AutofillProviderImpl(context, containerView);
     }
 
     void startYourEngines(boolean onMainThread) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
index c2a36f0..417e9aa 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -36,9 +36,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.android_webview.AwAutofillManager;
-import org.chromium.android_webview.AwAutofillProvider;
-import org.chromium.android_webview.AwAutofillUMA;
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwContentsClient.AwWebResourceRequest;
 import org.chromium.android_webview.AwWebResourceResponse;
@@ -52,7 +49,10 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.MetricsUtils;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
+import org.chromium.components.autofill.AutofillManagerWrapper;
 import org.chromium.components.autofill.AutofillProvider;
+import org.chromium.components.autofill.AutofillProviderImpl;
+import org.chromium.components.autofill.AutofillProviderUMA;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -431,10 +431,10 @@
         public ArrayList<Pair<Integer, AutofillValue>> changedValues;
     }
 
-    private class TestAwAutofillManager extends AwAutofillManager {
+    private class TestAutofillManagerWrapper extends AutofillManagerWrapper {
         private boolean mDisabled;
 
-        public TestAwAutofillManager(Context context) {
+        public TestAutofillManagerWrapper(Context context) {
             super(context);
         }
 
@@ -613,31 +613,31 @@
         private void initDeltaSamples() {
             TestThreadUtils.runOnUiThreadBlocking(() -> {
                 mSessionDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>();
-                for (int i = 0; i < AwAutofillUMA.AUTOFILL_SESSION_HISTOGRAM_COUNT; i++) {
-                    mSessionDelta.put(
-                            new MetricsUtils.HistogramDelta(
-                                    AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION, i),
+                for (int i = 0; i < AutofillProviderUMA.AUTOFILL_SESSION_HISTOGRAM_COUNT; i++) {
+                    mSessionDelta.put(new MetricsUtils.HistogramDelta(
+                                              AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION, i),
                             i);
                 }
                 mSubmissionSourceDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>();
-                for (int i = 0; i < AwAutofillUMA.SUBMISSION_SOURCE_HISTOGRAM_COUNT; i++) {
+                for (int i = 0; i < AutofillProviderUMA.SUBMISSION_SOURCE_HISTOGRAM_COUNT; i++) {
                     mSubmissionSourceDelta.put(
                             new MetricsUtils.HistogramDelta(
-                                    AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE, i),
+                                    AutofillProviderUMA.UMA_AUTOFILL_SUBMISSION_SOURCE, i),
                             i);
                 }
                 mAutofillWebViewViewEnabled = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 1 /*true*/);
+                        AutofillProviderUMA.UMA_AUTOFILL_ENABLED, 1 /*true*/);
                 mAutofillWebViewViewDisabled = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 0 /*false*/);
+                        AutofillProviderUMA.UMA_AUTOFILL_ENABLED, 0 /*false*/);
                 mAutofillWebViewCreatedByActivityContext = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 1);
+                        AutofillProviderUMA.UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT, 1);
                 mAutofillWebViewCreatedByAppContext = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 0);
+                        AutofillProviderUMA.UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT, 0);
                 mUserChangedAutofilledField = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 1 /*true*/);
+                        AutofillProviderUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 1 /*true*/);
                 mUserChangedNonAutofilledField = new MetricsUtils.HistogramDelta(
-                        AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 0 /*falsTe*/);
+                        AutofillProviderUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD,
+                        0 /*falsTe*/);
             });
         }
 
@@ -718,7 +718,7 @@
     private ConcurrentLinkedQueue<Integer> mEventQueue = new ConcurrentLinkedQueue<>();
     private TestValues mTestValues = new TestValues();
     private int mSubmissionSource;
-    private TestAwAutofillManager mTestAwAutofillManager;
+    private TestAutofillManagerWrapper mTestAutofillManagerWrapper;
     private AwAutofillSessionUMATestHelper mUMATestHelper;
 
     @Before
@@ -730,9 +730,9 @@
                     @Override
                     public AutofillProvider createAutofillProvider(
                             Context context, ViewGroup containerView) {
-                        mTestAwAutofillManager = new TestAwAutofillManager(context);
-                        return new AwAutofillProvider(
-                                containerView, mTestAwAutofillManager, context);
+                        mTestAutofillManagerWrapper = new TestAutofillManagerWrapper(context);
+                        return new AutofillProviderImpl(
+                                containerView, mTestAutofillManagerWrapper, context);
                     }
                 });
         mAwContents = mTestContainerView.getAwContents();
@@ -1505,9 +1505,10 @@
             mUMATestHelper.simulateUserSelectSuggestion();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
         } finally {
             webServer.shutdown();
         }
@@ -1525,7 +1526,8 @@
             mUMATestHelper.simulateUserSelectSuggestion();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.startNewSession();
-            assertEquals(AwAutofillUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(
+                    AutofillProviderUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
@@ -1541,20 +1543,20 @@
         TestWebServer webServer = TestWebServer.start();
         try {
             int count = mUMATestHelper.getHistogramSampleCount(
-                    AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_SUGGESTION_TIME);
+                    AutofillProviderUMA.UMA_AUTOFILL_SUGGESTION_TIME);
             mUMATestHelper.triggerAutofill(webServer);
             invokeOnProvideAutoFillVirtualStructure();
             invokeOnInputUIShown();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.startNewSession();
-            assertEquals(
-                    AwAutofillUMA.USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA
+                                 .USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
             assertEquals(count + 1,
                     mUMATestHelper.getHistogramSampleCount(
-                            AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_SUGGESTION_TIME));
+                            AutofillProviderUMA.UMA_AUTOFILL_SUGGESTION_TIME));
         } finally {
             webServer.shutdown();
         }
@@ -1571,9 +1573,11 @@
             invokeOnInputUIShown();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(
+                    AutofillProviderUMA.USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
         } finally {
             webServer.shutdown();
         }
@@ -1589,7 +1593,7 @@
             invokeOnProvideAutoFillVirtualStructure();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.startNewSession();
-            assertEquals(AwAutofillUMA.NO_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.NO_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
@@ -1609,9 +1613,10 @@
             invokeOnProvideAutoFillVirtualStructure();
             mUMATestHelper.simulateUserChangeField();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
             mUMATestHelper.verifyUserChangedNonAutofilledField();
         } finally {
             webServer.shutdown();
@@ -1629,9 +1634,11 @@
             invokeOnInputUIShown();
             mUMATestHelper.simulateUserSelectSuggestion();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(
+                    AutofillProviderUMA.USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
             mUMATestHelper.verifyUserDidntChangeForm();
         } finally {
             webServer.shutdown();
@@ -1649,8 +1656,8 @@
             invokeOnInputUIShown();
             mUMATestHelper.simulateUserSelectSuggestion();
             mUMATestHelper.startNewSession();
-            assertEquals(
-                    AwAutofillUMA.USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA
+                                 .USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
@@ -1670,8 +1677,8 @@
             invokeOnProvideAutoFillVirtualStructure();
             invokeOnInputUIShown();
             mUMATestHelper.startNewSession();
-            assertEquals(
-                    AwAutofillUMA.USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA
+                                 .USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
@@ -1691,10 +1698,11 @@
             invokeOnProvideAutoFillVirtualStructure();
             invokeOnInputUIShown();
             mUMATestHelper.submitForm();
-            assertEquals(
-                    AwAutofillUMA.USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA
+                                 .USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
             mUMATestHelper.verifyUserDidntChangeForm();
         } finally {
             webServer.shutdown();
@@ -1710,7 +1718,7 @@
             mUMATestHelper.triggerAutofill(webServer);
             invokeOnProvideAutoFillVirtualStructure();
             mUMATestHelper.startNewSession();
-            assertEquals(AwAutofillUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
@@ -1729,9 +1737,10 @@
             mUMATestHelper.triggerAutofill(webServer);
             invokeOnProvideAutoFillVirtualStructure();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
             mUMATestHelper.verifyUserDidntChangeForm();
         } finally {
             webServer.shutdown();
@@ -1746,8 +1755,8 @@
         try {
             mUMATestHelper.triggerAutofill(webServer);
             mUMATestHelper.startNewSession();
-            assertEquals(
-                    AwAutofillUMA.NO_CALLBACK_FORM_FRAMEWORK, mUMATestHelper.getSessionValue());
+            assertEquals(AutofillProviderUMA.NO_CALLBACK_FORM_FRAMEWORK,
+                    mUMATestHelper.getSessionValue());
             assertEquals(AwAutofillSessionUMATestHelper.NO_FORM_SUBMISSION,
                     mUMATestHelper.getSubmissionSourceValue());
         } finally {
@@ -1759,7 +1768,7 @@
     @SmallTest
     @Feature({"AndroidWebView"})
     public void testUMAAutofillDisabled() throws Throwable {
-        mTestAwAutofillManager.setDisabled();
+        mTestAutofillManagerWrapper.setDisabled();
         TestWebServer webServer = TestWebServer.start();
         try {
             mUMATestHelper.triggerAutofill(webServer);
@@ -1798,9 +1807,10 @@
             mUMATestHelper.simulateUserSelectSuggestion();
             mUMATestHelper.simulateUserChangeAutofilledField();
             mUMATestHelper.submitForm();
-            assertEquals(AwAutofillUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
+            assertEquals(AutofillProviderUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED,
                     mUMATestHelper.getSessionValue());
-            assertEquals(AwAutofillUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
+            assertEquals(
+                    AutofillProviderUMA.FORM_SUBMISSION, mUMATestHelper.getSubmissionSourceValue());
             mUMATestHelper.verifyUserChangedAutofilledField();
         } finally {
             webServer.shutdown();
@@ -1840,7 +1850,7 @@
             List<Integer> expectedValues = new ArrayList<>();
 
             // On Android version below P scroll triggers additional
-            // AUTOFILL_VIEW_ENTERED (@see AwAutofillProvider#onTextFieldDidScroll).
+            // AUTOFILL_VIEW_ENTERED (@see AutofillProviderImpl#onTextFieldDidScroll).
             if (VERSION.SDK_INT < Build.VERSION_CODES.P) {
                 expectedValues.add(AUTOFILL_VIEW_ENTERED);
             }
@@ -1889,7 +1899,8 @@
     }
 
     private void invokeOnInputUIShown() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> mTestAwAutofillManager.notifyInputUIChange());
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> mTestAutofillManagerWrapper.notifyInputUIChange());
     }
 
     private int getCallbackCount() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploaderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java
similarity index 94%
rename from android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploaderTest.java
rename to android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java
index 15d3b18d..fa48ac22 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploaderTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java
@@ -27,11 +27,11 @@
 import org.chromium.components.minidump_uploader.CrashFileManager;
 import org.chromium.components.minidump_uploader.CrashTestRule;
 import org.chromium.components.minidump_uploader.CrashTestRule.MockCrashReportingPermissionManager;
+import org.chromium.components.minidump_uploader.MinidumpUploadJob;
+import org.chromium.components.minidump_uploader.MinidumpUploadJobImpl;
 import org.chromium.components.minidump_uploader.MinidumpUploadTestUtility;
-import org.chromium.components.minidump_uploader.MinidumpUploader;
 import org.chromium.components.minidump_uploader.MinidumpUploaderDelegate;
-import org.chromium.components.minidump_uploader.MinidumpUploaderImpl;
-import org.chromium.components.minidump_uploader.TestMinidumpUploaderImpl;
+import org.chromium.components.minidump_uploader.TestMinidumpUploadJobImpl;
 import org.chromium.components.minidump_uploader.util.CrashReportingPermissionManager;
 import org.chromium.components.version_info.Channel;
 
@@ -46,7 +46,7 @@
  */
 @RunWith(AwJUnit4ClassRunner.class)
 @OnlyRunIn(SINGLE_PROCESS)
-public class MinidumpUploaderTest {
+public class MinidumpUploadJobTest {
     @Rule
     public CrashTestRule mTestRule = new CrashTestRule() {
         @Override
@@ -101,16 +101,16 @@
             new TestSamplingDelegate(Channel.UNKNOWN, 0);
 
     /**
-     * Ensure MinidumpUploaderImpl doesn't crash even if the WebView Crash dir doesn't exist (could
+     * Ensure MinidumpUploadJobImpl doesn't crash even if the WebView Crash dir doesn't exist (could
      * happen e.g. if a Job persists across WebView-updates?
      *
-     * MinidumpUploaderImpl should automatically recreate the directory.
+     * MinidumpUploadJobImpl should automatically recreate the directory.
      */
     @Test
     @MediumTest
     public void testUploadingWithoutCrashDir() {
         File webviewCrashDir = mTestRule.getExistingCacheDir();
-        // Delete the WebView crash directory to ensure MinidumpUploader doesn't crash without it.
+        // Delete the WebView crash directory to ensure MinidumpUploadJob doesn't crash without it.
         FileUtils.recursivelyDeleteFile(webviewCrashDir);
         Assert.assertFalse(webviewCrashDir.exists());
 
@@ -119,10 +119,10 @@
                 new MockCrashReportingPermissionManager() {
                     { mIsEnabledForTests = true; }
                 };
-        MinidumpUploader minidumpUploader =
+        MinidumpUploadJob minidumpUploadJob =
                 // Use AwMinidumpUploaderDelegate instead of TestMinidumpUploaderDelegate here
                 // since AwMinidumpUploaderDelegate defines the WebView crash directory.
-                new TestMinidumpUploaderImpl(new AwMinidumpUploaderDelegate(
+                new TestMinidumpUploadJobImpl(new AwMinidumpUploaderDelegate(
                         TEST_SAMPLING_DELEGATE) {
                     @Override
                     public CrashReportingPermissionManager createCrashReportingPermissionManager() {
@@ -132,7 +132,7 @@
 
         // Ensure that we don't crash when trying to upload minidumps without a crash directory.
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, false /* expectReschedule */);
+                minidumpUploadJob, false /* expectReschedule */);
     }
 
     /**
@@ -278,7 +278,7 @@
         PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(/* userConsent */ true));
         MinidumpUploaderDelegate delegate = new TestCrashSamplingMinidumpUploaderDelegate(
                 new TestSamplingDelegate(channel, samplePercentage), isSampled);
-        MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(delegate);
+        MinidumpUploadJob minidumpUploadJob = new TestMinidumpUploadJobImpl(delegate);
 
         File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0.try0");
         File secondFile = createMinidumpFileInCrashDir("12_abcd.dmp0.try0");
@@ -288,7 +288,7 @@
                 secondFile.getName().replace(".dmp", isSampled ? ".up" : ".skipped"));
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, false /* expectReschedule */);
+                minidumpUploadJob, false /* expectReschedule */);
 
         Assert.assertFalse(firstFile.exists());
         Assert.assertTrue(expectedFirstFile.exists());
@@ -354,7 +354,7 @@
         PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(userConsent));
         MinidumpUploaderDelegate delegate =
                 new WebViewUserConsentMinidumpUploaderDelegate(userConsent);
-        MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(delegate);
+        MinidumpUploadJob minidumpUploadJob = new TestMinidumpUploadJobImpl(delegate);
 
         File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0.try0");
         File secondFile = createMinidumpFileInCrashDir("12_abcd.dmp0.try0");
@@ -364,7 +364,7 @@
                 secondFile.getName().replace(".dmp", userConsent ? ".up" : ".skipped"));
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, false /* expectReschedule */);
+                minidumpUploadJob, false /* expectReschedule */);
 
         Assert.assertFalse(firstFile.exists());
         Assert.assertTrue(expectedFirstFile.exists());
@@ -436,7 +436,7 @@
         Assert.assertEquals(minidumps.length, uids.length);
         // Ensure the upload service minidump directory is empty before we start copying files.
         File[] initialMinidumps = fileManager.getMinidumpsReadyForUpload(
-                MinidumpUploaderImpl.MAX_UPLOAD_TRIES_ALLOWED);
+                MinidumpUploadJobImpl.MAX_UPLOAD_TRIES_ALLOWED);
         Assert.assertEquals(0, initialMinidumps.length);
 
         // Open file descriptors to the files and then delete the files.
@@ -459,11 +459,11 @@
                 new MockCrashReportingPermissionManager() {
                     { mIsEnabledForTests = true; }
                 };
-        MinidumpUploader minidumpUploader =
+        MinidumpUploadJob minidumpUploadJob =
                 // Use AwMinidumpUploaderDelegate instead of TestMinidumpUploaderDelegate to ensure
                 // AwMinidumpUploaderDelegate works well together with the minidump-copying methods
                 // of CrashReceiverService.
-                new TestMinidumpUploaderImpl(new AwMinidumpUploaderDelegate(
+                new TestMinidumpUploadJobImpl(new AwMinidumpUploaderDelegate(
                         TEST_SAMPLING_DELEGATE) {
                     @Override
                     public CrashReportingPermissionManager createCrashReportingPermissionManager() {
@@ -472,10 +472,10 @@
                 });
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, false /* expectReschedule */);
+                minidumpUploadJob, false /* expectReschedule */);
         // Ensure there are no minidumps left to upload.
         File[] nonUploadedMinidumps = fileManager.getMinidumpsReadyForUpload(
-                MinidumpUploaderImpl.MAX_UPLOAD_TRIES_ALLOWED);
+                MinidumpUploadJobImpl.MAX_UPLOAD_TRIES_ALLOWED);
         Assert.assertEquals(0, nonUploadedMinidumps.length);
 
         File[] uploadedFiles = fileManager.getAllUploadedFiles();
diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn
index e9e59f6..05e5768 100644
--- a/android_webview/nonembedded/BUILD.gn
+++ b/android_webview/nonembedded/BUILD.gn
@@ -153,4 +153,14 @@
                   "library=libmonochrome_64.so",
                 ]
   }
+
+  jinja_template("trichrome_webview_32_manifest") {
+    input = "java/AndroidManifest.xml"
+    output = trichrome_webview_32_android_manifest
+    variables = trichrome_jinja_variables + [
+                  "trichrome_version=$trichrome_32_version_code",
+                  "manifest_package=$system_webview_package_name",
+                  "library=libmonochrome.so",
+                ]
+  }
 }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwMinidumpUploadJobService.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwMinidumpUploadJobService.java
index 078ed237..eedb31ba 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwMinidumpUploadJobService.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwMinidumpUploadJobService.java
@@ -6,9 +6,9 @@
 
 import android.os.PersistableBundle;
 
+import org.chromium.components.minidump_uploader.MinidumpUploadJob;
+import org.chromium.components.minidump_uploader.MinidumpUploadJobImpl;
 import org.chromium.components.minidump_uploader.MinidumpUploadJobService;
-import org.chromium.components.minidump_uploader.MinidumpUploader;
-import org.chromium.components.minidump_uploader.MinidumpUploaderImpl;
 
 /**
  * Class that interacts with the Android JobScheduler to upload Minidumps at appropriate times.
@@ -16,7 +16,7 @@
 // OBS: This class needs to be public to be started from android.app.ActivityThread.
 public class AwMinidumpUploadJobService extends MinidumpUploadJobService {
     @Override
-    protected MinidumpUploader createMinidumpUploader(PersistableBundle unusedExtras) {
-        return new MinidumpUploaderImpl(new AwMinidumpUploaderDelegate());
+    protected MinidumpUploadJob createMinidumpUploadJob(PersistableBundle unusedExtras) {
+        return new MinidumpUploadJobImpl(new AwMinidumpUploaderDelegate());
     }
 }
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni
index 75e879f0..92a7eb7 100644
--- a/android_webview/system_webview_apk_tmpl.gni
+++ b/android_webview/system_webview_apk_tmpl.gni
@@ -69,17 +69,17 @@
     _use_trichrome_library =
         defined(use_trichrome_library) && use_trichrome_library
 
-    if (!_use_trichrome_library) {
-      deps += [ "//android_webview:monochrome_webview_assets" ]
-    }
+    # Pure 32-bit implies a 32-bit only Webview built on a 64-bit configuration.
+    _pure_32_bit =
+        android_64bit_target_cpu && defined(invoker.include_64_bit_webview) &&
+        !invoker.include_64_bit_webview
+    not_needed([ "_pure_32_bit" ])
 
     # Flag whether additional deps and libs should be included for each ABI.
     _include_primary_support = false
     _include_secondary_support = false
 
     if (!_use_trichrome_library) {
-      shared_libraries = [ "//android_webview:libwebviewchromium" ]
-      _include_primary_support = true
       if (_is_bundle_module) {
         # TODO(b/146491000): aapt2 currently doesn't support the --shared-lib
         # flag for bundles, so this will only work on M+.
@@ -87,10 +87,16 @@
       } else {
         shared_resources = true
       }
+
+      if (!android_64bit_target_cpu || !_pure_32_bit) {
+        shared_libraries = [ "//android_webview:libwebviewchromium" ]
+        _include_primary_support = true
+      }
       if (android_64bit_target_cpu) {
         secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
         _include_secondary_support = true
       }
+      deps += [ "//third_party/icu:icu_assets" ]
     } else {
       uncompress_shared_libraries = true
       app_as_shared_lib = true
@@ -102,19 +108,12 @@
           native_lib_placeholders = [ "libdummy.so" ]
           if (invoker.include_32_bit_webview) {
             secondary_abi_shared_libraries = [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
-            deps += [ "//android_webview:v8_snapshot_secondary_abi_assets" ]
             _include_secondary_support = true
           }
         } else {
           if (invoker.include_64_bit_webview) {
             shared_libraries = [ "//android_webview:monochrome" ]
             _include_primary_support = true
-            if (use_v8_context_snapshot) {
-              deps +=
-                  [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ]
-            } else {
-              deps += [ "//v8:v8_external_startup_data_assets" ]
-            }
           }
           secondary_native_lib_placeholders = [ "libdummy.so" ]
         }
@@ -125,13 +124,17 @@
 
     if (_include_primary_support) {
       deps += [
+        "//android_webview:webview_primary_abi_assets",
         "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
       ]
       loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
     }
     if (_include_secondary_support) {
       _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
-      deps += [ _trampoline ]
+      deps += [
+        "//android_webview:webview_secondary_abi_assets",
+        _trampoline,
+      ]
       _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
       secondary_abi_loadable_modules =
           [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
@@ -202,12 +205,26 @@
         } else {
           version_code = trichrome_version_code
         }
-      } else if (android_channel == "dev") {
-        version_code = webview_dev_version_code
-      } else if (android_channel == "beta") {
-        version_code = webview_beta_version_code
       } else {
-        version_code = webview_stable_version_code
+        if (android_channel == "dev") {
+          if (_pure_32_bit) {
+            version_code = webview_32_dev_version_code
+          } else {
+            version_code = webview_dev_version_code
+          }
+        } else if (android_channel == "beta") {
+          if (_pure_32_bit) {
+            version_code = webview_32_beta_version_code
+          } else {
+            version_code = webview_beta_version_code
+          }
+        } else {
+          if (_pure_32_bit) {
+            version_code = webview_32_stable_version_code
+          } else {
+            version_code = webview_stable_version_code
+          }
+        }
       }
     }
     if (!defined(version_name)) {
diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_webview_bundle.gni
index d298edd..f92a58b 100644
--- a/android_webview/system_webview_bundle.gni
+++ b/android_webview/system_webview_bundle.gni
@@ -11,7 +11,11 @@
     proguard_enabled = !is_java_debug
     enable_language_splits = true
     system_image_locale_whitelist = locales
-    is_multi_abi = android_64bit_target_cpu
+    is_multi_abi =
+        android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) ||
+                                     invoker.include_64_bit_webview) &&
+        (!defined(invoker.include_32_bit_webview) ||
+         invoker.include_32_bit_webview)
 
     if (!defined(proguard_android_sdk_dep)) {
       proguard_android_sdk_dep = webview_framework_dep
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index b1ddd7ae..d076864 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -296,7 +296,7 @@
     "../javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashInfoCollectorTest.java",
     "../javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashLogParserTest.java",
     "../javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java",
-    "../javatests/src/org/chromium/android_webview/test/services/MinidumpUploaderTest.java",
+    "../javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java",
     "../javatests/src/org/chromium/android_webview/test/services/MockVariationsSeedServer.java",
     "../javatests/src/org/chromium/android_webview/test/services/VariationsSeedServerTest.java",
     "../javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java",
diff --git a/android_webview/variables.gni b/android_webview/variables.gni
index 299b209..f3142e7 100644
--- a/android_webview/variables.gni
+++ b/android_webview/variables.gni
@@ -14,6 +14,8 @@
 trichrome_webview_android_manifest =
     "$root_gen_dir/android_webview/trichrome_webview_apk/AndroidManifest.xml"
 trichrome_webview_64_32_android_manifest = "$root_gen_dir/android_webview/trichrome_webview_64_32_apk/AndroidManifest.xml"
+trichrome_webview_32_android_manifest =
+    "$root_gen_dir/android_webview/trichrome_webview_32_apk/AndroidManifest.xml"
 
 upstream_only_webview_deps = [
   "//android_webview:platform_service_bridge_upstream_implementation_java",
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 77096bea..3166164 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -634,7 +634,9 @@
         OVERVIEW_ANIMATION_DROP_TARGET_FADE, drop_target_window);
     drop_target_widget_->SetOpacity(1.f);
   }
-  overview_session_->AddItem(drop_target_window, /*reposition=*/true, animate);
+  const size_t position = FindInsertionIndex(dragged_window);
+  overview_session_->AddItem(drop_target_window, /*reposition=*/true, animate,
+                             /*ignored_items=*/{}, position);
 }
 
 void OverviewGrid::RemoveDropTarget() {
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index a7230a0..975269bf 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -6255,6 +6255,51 @@
   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
 }
 
+// Verify the drop target positions for multi-display dragging.
+TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
+       DropTargetPositionTest) {
+  wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
+  UpdateDisplay("800x600,800x600");
+  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+  ASSERT_EQ(2u, root_windows.size());
+  const display::Display display_with_root1 =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[0]);
+  const display::Display display_with_root2 =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]);
+  const gfx::Rect bounds_within_root1(0, 0, 400, 400);
+  const gfx::Rect bounds_within_root2(800, 0, 400, 400);
+  // Named for MRU order, which is in reverse of creation order.
+  std::unique_ptr<aura::Window> window6 = CreateTestWindow(bounds_within_root2);
+  std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds_within_root1);
+  std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds_within_root2);
+  std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root1);
+  std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root2);
+  std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
+  ToggleOverview();
+  OverviewGrid* grid1 =
+      overview_session()->GetGridWithRootWindow(root_windows[0]);
+  OverviewGrid* grid2 =
+      overview_session()->GetGridWithRootWindow(root_windows[1]);
+  OverviewItem* item4 = grid2->GetOverviewItemContaining(window4.get());
+  // Start dragging |item4| from |grid2|.
+  cursor_manager->SetDisplay(display_with_root2);
+  overview_session()->InitiateDrag(item4, item4->target_bounds().CenterPoint(),
+                                   /*is_touch_dragging=*/false);
+  overview_session()->Drag(item4, gfx::PointF(1200.f, 0.f));
+  // On the grid where the drag starts (|grid2|), the drop target is inserted at
+  // the index immediately following the dragged item (|item4|).
+  ASSERT_EQ(4u, grid2->window_list().size());
+  EXPECT_EQ(grid2->GetDropTarget(), grid2->window_list()[2].get());
+  // Drag over |grid1|.
+  cursor_manager->SetDisplay(display_with_root1);
+  overview_session()->Drag(item4, gfx::PointF(400.f, 0.f));
+  // On other grids (such as |grid1|), the drop target is inserted at the
+  // correct position according to MRU order (between the overview items for
+  // |window3| and |window5|).
+  ASSERT_EQ(4u, grid1->window_list().size());
+  EXPECT_EQ(grid1->GetDropTarget(), grid1->window_list()[2].get());
+}
+
 // Verify that the drop target in each overview grid has bounds representing
 // anticipation that if the dragged window is dropped into that grid, it will
 // shrink to fit into the corresponding work area.
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index c67698a..ec4e28df 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -4507,23 +4507,22 @@
 
 class TestWindowDelegateWithWidget : public views::WidgetDelegate {
  public:
-  TestWindowDelegateWithWidget(bool can_activate)
-      : can_activate_(can_activate) {}
+  TestWindowDelegateWithWidget(bool can_resize) : can_resize_(can_resize) {}
   ~TestWindowDelegateWithWidget() override = default;
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
   views::Widget* GetWidget() override { return widget_; }
   const views::Widget* GetWidget() const override { return widget_; }
-  bool CanActivate() const override { return can_activate_; }
-  bool CanResize() const override { return true; }
+  bool CanActivate() const override { return true; }
+  bool CanResize() const override { return can_resize_; }
   bool CanMaximize() const override { return true; }
   bool ShouldAdvanceFocusToTopLevelWidget() const override { return true; }
 
   void set_widget(views::Widget* widget) { widget_ = widget; }
 
  private:
-  bool can_activate_ = false;
+  bool can_resize_;
   views::Widget* widget_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegateWithWidget);
@@ -4542,12 +4541,12 @@
   }
 
  protected:
-  std::unique_ptr<aura::Window> CreateTestWindowWithWidget(bool can_activate) {
+  std::unique_ptr<aura::Window> CreateTestWindowWithWidget(bool can_resize) {
     views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
     params.show_state = ui::SHOW_STATE_MAXIMIZED;
     views::Widget* widget = new views::Widget;
     std::unique_ptr<TestWindowDelegateWithWidget> widget_delegate =
-        std::make_unique<TestWindowDelegateWithWidget>(can_activate);
+        std::make_unique<TestWindowDelegateWithWidget>(can_resize);
     widget_delegate->set_widget(widget);
     params.delegate = widget_delegate.release();
     params.context = CurrentContext();
@@ -4556,8 +4555,8 @@
     return base::WrapUnique<aura::Window>(widget->GetNativeView());
   }
 
-  void InitializeWindow(bool can_activate = true) {
-    window_ = CreateTestWindowWithWidget(can_activate);
+  void InitializeWindow(bool can_resize = true) {
+    window_ = CreateTestWindowWithWidget(can_resize);
   }
 
   // Sends a gesture scroll sequence to TabletModeAppWindowDragController.
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h
index 0d617ff..a516861 100644
--- a/base/debug/stack_trace.h
+++ b/base/debug/stack_trace.h
@@ -87,7 +87,9 @@
   // Copying and assignment are allowed with the default functions.
 
   // Gets an array of instruction pointer values. |*count| will be set to the
-  // number of elements in the returned array.
+  // number of elements in the returned array. Addresses()[0] will contain an
+  // address from the leaf function, and Addresses()[count-1] will contain an
+  // address from the root function (i.e.; the thread's entry point).
   const void* const* Addresses(size_t* count) const;
 
   // Prints the stack trace to stderr.
diff --git a/base/files/file_proxy_unittest.cc b/base/files/file_proxy_unittest.cc
index 9fccfff..e410d431 100644
--- a/base/files/file_proxy_unittest.cc
+++ b/base/files/file_proxy_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/test/task_environment.h"
+#include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
@@ -229,7 +230,16 @@
   EXPECT_EQ("test", data);
 
   // Make sure we can & do delete the created file to prevent leaks on the bots.
-  EXPECT_TRUE(base::DeleteFile(path_, false));
+  // Try a few times because files may be locked by anti-virus or other.
+  bool deleted_temp_file = false;
+  for (int i = 0; !deleted_temp_file && i < 3; ++i) {
+    if (base::DeleteFile(path_, false))
+      deleted_temp_file = true;
+    else
+      // Wait one second and then try again
+      PlatformThread::Sleep(TimeDelta::FromSeconds(1));
+  }
+  EXPECT_TRUE(deleted_temp_file);
 }
 
 TEST_F(FileProxyTest, SetAndTake) {
diff --git a/base/profiler/profile_builder.h b/base/profiler/profile_builder.h
index fb49153..6919594 100644
--- a/base/profiler/profile_builder.h
+++ b/base/profiler/profile_builder.h
@@ -62,7 +62,8 @@
   virtual void RecordMetadata(MetadataProvider* metadata_provider) {}
 
   // Records a new set of frames. Invoked when sampling a sample completes.
-  virtual void OnSampleCompleted(std::vector<Frame> frames) = 0;
+  virtual void OnSampleCompleted(std::vector<Frame> frames,
+                                 TimeTicks sample_timestamp) = 0;
 
   // Finishes the profile construction with |profile_duration| and
   // |sampling_period|. Invoked when sampling a profile completes.
diff --git a/base/profiler/stack_copier.h b/base/profiler/stack_copier.h
index 921e1324..a504886 100644
--- a/base/profiler/stack_copier.h
+++ b/base/profiler/stack_copier.h
@@ -9,6 +9,7 @@
 
 #include "base/base_export.h"
 #include "base/profiler/register_context.h"
+#include "base/time/time.h"
 
 namespace base {
 
@@ -26,11 +27,12 @@
 
   // Copies the thread's register context into |thread_context|, the stack into
   // |stack_buffer|, and the top of stack address into |stack_top|. Records
-  // metadata while the thread is suspended via |profile_builder|. Returns true
-  // if successful.
+  // metadata while the thread is suspended via |profile_builder|. Records
+  // |timestamp| at the time the stack was copied. Returns true if successful.
   virtual bool CopyStack(StackBuffer* stack_buffer,
                          uintptr_t* stack_top,
                          ProfileBuilder* profile_builder,
+                         TimeTicks* timestamp,
                          RegisterContext* thread_context) = 0;
 
  protected:
diff --git a/base/profiler/stack_copier_signal.cc b/base/profiler/stack_copier_signal.cc
index 77f3480a9..372038e 100644
--- a/base/profiler/stack_copier_signal.cc
+++ b/base/profiler/stack_copier_signal.cc
@@ -82,13 +82,19 @@
   AsyncSafeWaitableEvent* event;
 
   // Return values:
+
   // Successfully copied the stack segment.
   bool* success;
+
   // The thread context of the leaf function.
   mcontext_t* context;
+
   // Buffer to copy the stack segment.
   StackBuffer* stack_buffer;
   const uint8_t** stack_copy_bottom;
+
+  // The timestamp when the stack was copied.
+  TimeTicks* timestamp;
 };
 
 // Pointer to the parameters to be "passed" to the CopyStackSignalHandler() from
@@ -101,6 +107,11 @@
 // function may only call reentrant code.
 void CopyStackSignalHandler(int n, siginfo_t* siginfo, void* sigcontext) {
   HandlerParams* params = g_handler_params.load(std::memory_order_acquire);
+
+  // TimeTicks::Now() is implemented in terms of clock_gettime on Linux, which
+  // is signal safe per the signal-safety(7) man page.
+  *params->timestamp = TimeTicks::Now();
+
   ScopedEventSignaller e(params->event);
   *params->success = false;
 
@@ -176,13 +187,15 @@
 bool StackCopierSignal::CopyStack(StackBuffer* stack_buffer,
                                   uintptr_t* stack_top,
                                   ProfileBuilder* profile_builder,
+                                  TimeTicks* timestamp,
                                   RegisterContext* thread_context) {
   AsyncSafeWaitableEvent wait_event;
   bool copied = false;
   const uint8_t* stack_copy_bottom = nullptr;
   const uintptr_t stack_base_address = thread_delegate_->GetStackBaseAddress();
   HandlerParams params = {stack_base_address, &wait_event,  &copied,
-                          thread_context,     stack_buffer, &stack_copy_bottom};
+                          thread_context,     stack_buffer, &stack_copy_bottom,
+                          timestamp};
   {
     ScopedSetSignalHandlerParams scoped_handler_params(&params);
 
diff --git a/base/profiler/stack_copier_signal.h b/base/profiler/stack_copier_signal.h
index 75583ae..609eb49 100644
--- a/base/profiler/stack_copier_signal.h
+++ b/base/profiler/stack_copier_signal.h
@@ -25,6 +25,7 @@
   bool CopyStack(StackBuffer* stack_buffer,
                  uintptr_t* stack_top,
                  ProfileBuilder* profile_builder,
+                 TimeTicks* timestamp,
                  RegisterContext* thread_context) override;
 
   using StackCopier::CopyStackContentsAndRewritePointers;
diff --git a/base/profiler/stack_copier_signal_unittest.cc b/base/profiler/stack_copier_signal_unittest.cc
index 02999a3..685b93b 100644
--- a/base/profiler/stack_copier_signal_unittest.cc
+++ b/base/profiler/stack_copier_signal_unittest.cc
@@ -35,7 +35,8 @@
   void RecordMetadata(
       base::ProfileBuilder::MetadataProvider* metadata_provider) override {}
 
-  void OnSampleCompleted(std::vector<Frame> frames) override {}
+  void OnSampleCompleted(std::vector<Frame> frames,
+                         TimeTicks sample_timestamp) override {}
   void OnProfileCompleted(TimeDelta profile_duration,
                           TimeDelta sampling_period) override {}
 
@@ -95,6 +96,7 @@
   memset(stack_buffer.buffer(), 0, stack_buffer.size());
   uintptr_t stack_top = 0;
   TestProfileBuilder profiler_builder;
+  TimeTicks timestamp;
   RegisterContext context;
 
   StackCopierSignal copier(std::make_unique<ThreadDelegatePosix>(
@@ -106,8 +108,8 @@
   for (size_t i = 0; i < size(kStackSentinels); ++i)
     sentinels[i] = kStackSentinels[i];
 
-  bool result =
-      copier.CopyStack(&stack_buffer, &stack_top, &profiler_builder, &context);
+  bool result = copier.CopyStack(&stack_buffer, &stack_top, &profiler_builder,
+                                 &timestamp, &context);
   ASSERT_TRUE(result);
 
   uint32_t* const end = reinterpret_cast<uint32_t*>(stack_top);
@@ -120,6 +122,33 @@
   EXPECT_NE(end, sentinel_location);
 }
 
+// TSAN hangs on the AsyncSafeWaitableEvent FUTEX_WAIT call.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_CopyStackTimestamp DISABLED_CopyStackTimestamp
+#else
+#define MAYBE_CopyStackTimestamp CopyStackTimestamp
+#endif
+TEST(StackCopierSignalTest, MAYBE_CopyStackTimestamp) {
+  StackBuffer stack_buffer(/* buffer_size = */ 1 << 20);
+  memset(stack_buffer.buffer(), 0, stack_buffer.size());
+  uintptr_t stack_top = 0;
+  TestProfileBuilder profiler_builder;
+  TimeTicks timestamp;
+  RegisterContext context;
+
+  StackCopierSignal copier(std::make_unique<ThreadDelegatePosix>(
+      GetSamplingProfilerCurrentThreadToken()));
+
+  TimeTicks before = TimeTicks::Now();
+  bool result = copier.CopyStack(&stack_buffer, &stack_top, &profiler_builder,
+                                 &timestamp, &context);
+  TimeTicks after = TimeTicks::Now();
+  ASSERT_TRUE(result);
+
+  EXPECT_GE(timestamp, before);
+  EXPECT_LE(timestamp, after);
+}
+
 // Limit to 32-bit Android, which is the platform we care about for this
 // functionality. The test is broken on too many other varied platforms to try
 // to selectively disable.
@@ -133,6 +162,7 @@
   memset(stack_buffer.buffer(), 0, stack_buffer.size());
   uintptr_t stack_top = 0;
   TestProfileBuilder profiler_builder;
+  TimeTicks timestamp;
   RegisterContext context{};
 
   TargetThread target_thread;
@@ -142,8 +172,8 @@
 
   StackCopierSignal copier(std::make_unique<ThreadDelegatePosix>(thread_token));
 
-  bool result =
-      copier.CopyStack(&stack_buffer, &stack_top, &profiler_builder, &context);
+  bool result = copier.CopyStack(&stack_buffer, &stack_top, &profiler_builder,
+                                 &timestamp, &context);
   ASSERT_TRUE(result);
 
   target_thread.NotifyCopyFinished();
diff --git a/base/profiler/stack_copier_suspend.cc b/base/profiler/stack_copier_suspend.cc
index fbca633..ecf4e95 100644
--- a/base/profiler/stack_copier_suspend.cc
+++ b/base/profiler/stack_copier_suspend.cc
@@ -26,6 +26,7 @@
 bool StackCopierSuspend::CopyStack(StackBuffer* stack_buffer,
                                    uintptr_t* stack_top,
                                    ProfileBuilder* profile_builder,
+                                   TimeTicks* timestamp,
                                    RegisterContext* thread_context) {
   const uintptr_t top = thread_delegate_->GetStackBaseAddress();
   uintptr_t bottom = 0;
@@ -42,6 +43,10 @@
     std::unique_ptr<SuspendableThreadDelegate::ScopedSuspendThread>
         suspend_thread = thread_delegate_->CreateScopedSuspendThread();
 
+    // TimeTicks::Now() is implemented in terms of reads to the timer tick
+    // counter or TSC register on x86/x86_64 so is reentrant.
+    *timestamp = TimeTicks::Now();
+
     if (!suspend_thread->WasSuccessful())
       return false;
 
diff --git a/base/profiler/stack_copier_suspend.h b/base/profiler/stack_copier_suspend.h
index 6797625..78c7e80 100644
--- a/base/profiler/stack_copier_suspend.h
+++ b/base/profiler/stack_copier_suspend.h
@@ -27,6 +27,7 @@
   bool CopyStack(StackBuffer* stack_buffer,
                  uintptr_t* stack_top,
                  ProfileBuilder* profile_builder,
+                 TimeTicks* timestamp,
                  RegisterContext* thread_context) override;
 
  private:
diff --git a/base/profiler/stack_copier_suspend_unittest.cc b/base/profiler/stack_copier_suspend_unittest.cc
index f8b5857..a887adaf 100644
--- a/base/profiler/stack_copier_suspend_unittest.cc
+++ b/base/profiler/stack_copier_suspend_unittest.cc
@@ -98,7 +98,8 @@
     recorded_metadata_ = true;
   }
 
-  void OnSampleCompleted(std::vector<Frame> frames) override {}
+  void OnSampleCompleted(std::vector<Frame> frames,
+                         TimeTicks sample_timestamp) override {}
   void OnProfileCompleted(TimeDelta profile_duration,
                           TimeDelta sampling_period) override {}
 
@@ -117,9 +118,11 @@
       std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   uintptr_t stack_top = 0;
   TestProfileBuilder profile_builder;
+  TimeTicks timestamp;
   RegisterContext register_context{};
   stack_copier_suspend.CopyStack(stack_buffer.get(), &stack_top,
-                                 &profile_builder, &register_context);
+                                 &profile_builder, &timestamp,
+                                 &register_context);
 
   uintptr_t* stack_copy_bottom =
       reinterpret_cast<uintptr_t*>(stack_buffer.get()->buffer());
@@ -139,9 +142,11 @@
   stack_buffer->buffer()[0] = 100;
   uintptr_t stack_top = 0;
   TestProfileBuilder profile_builder;
+  TimeTicks timestamp;
   RegisterContext register_context{};
   stack_copier_suspend.CopyStack(stack_buffer.get(), &stack_top,
-                                 &profile_builder, &register_context);
+                                 &profile_builder, &timestamp,
+                                 &register_context);
 
   uintptr_t* stack_copy_bottom =
       reinterpret_cast<uintptr_t*>(stack_buffer.get()->buffer());
@@ -164,9 +169,11 @@
       std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   uintptr_t stack_top = 0;
   TestProfileBuilder profile_builder;
+  TimeTicks timestamp;
   RegisterContext register_context{};
   stack_copier_suspend.CopyStack(stack_buffer.get(), &stack_top,
-                                 &profile_builder, &register_context);
+                                 &profile_builder, &timestamp,
+                                 &register_context);
 
   uintptr_t* stack_copy_bottom =
       reinterpret_cast<uintptr_t*>(stack_buffer.get()->buffer());
@@ -178,6 +185,28 @@
                               sizeof(uintptr_t)));
 }
 
+TEST(StackCopierSuspendTest, CopyStackTimeStamp) {
+  const std::vector<uintptr_t> stack = {0};
+  StackCopierSuspend stack_copier_suspend(
+      std::make_unique<TestSuspendableThreadDelegate>(stack));
+
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
+  uintptr_t stack_top = 0;
+  TestProfileBuilder profile_builder;
+  TimeTicks timestamp;
+  RegisterContext register_context{};
+
+  TimeTicks before = TimeTicks::Now();
+  stack_copier_suspend.CopyStack(stack_buffer.get(), &stack_top,
+                                 &profile_builder, &timestamp,
+                                 &register_context);
+  TimeTicks after = TimeTicks::Now();
+
+  EXPECT_GE(timestamp, before);
+  EXPECT_LE(timestamp, after);
+}
+
 TEST(StackCopierSuspendTest, RewriteRegisters) {
   std::vector<uintptr_t> stack = {0, 1, 2};
   RegisterContext register_context{};
@@ -190,9 +219,11 @@
   std::unique_ptr<StackBuffer> stack_buffer =
       std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   uintptr_t stack_top = 0;
+  TimeTicks timestamp;
   TestProfileBuilder profile_builder;
   stack_copier_suspend.CopyStack(stack_buffer.get(), &stack_top,
-                                 &profile_builder, &register_context);
+                                 &profile_builder, &timestamp,
+                                 &register_context);
 
   uintptr_t stack_copy_bottom =
       reinterpret_cast<uintptr_t>(stack_buffer.get()->buffer());
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc
index f80e9c91..3d8b4d7 100644
--- a/base/profiler/stack_sampler_impl.cc
+++ b/base/profiler/stack_sampler_impl.cc
@@ -45,8 +45,9 @@
 
   RegisterContext thread_context;
   uintptr_t stack_top;
-  bool success = stack_copier_->CopyStack(stack_buffer, &stack_top,
-                                          profile_builder, &thread_context);
+  TimeTicks timestamp;
+  bool success = stack_copier_->CopyStack(
+      stack_buffer, &stack_top, profile_builder, &timestamp, &thread_context);
   if (!success)
     return;
 
@@ -55,7 +56,8 @@
 
   profile_builder->OnSampleCompleted(
       WalkStack(module_cache_, &thread_context, stack_top,
-                native_unwinder_.get(), aux_unwinder_.get()));
+                native_unwinder_.get(), aux_unwinder_.get()),
+      timestamp);
 }
 // static
 
diff --git a/base/profiler/stack_sampler_impl_unittest.cc b/base/profiler/stack_sampler_impl_unittest.cc
index 3ca4aff..e1912a6 100644
--- a/base/profiler/stack_sampler_impl_unittest.cc
+++ b/base/profiler/stack_sampler_impl_unittest.cc
@@ -37,32 +37,45 @@
   ModuleCache* GetModuleCache() override { return module_cache_; }
   void RecordMetadata(
       ProfileBuilder::MetadataProvider* metadata_provider) override {}
-  void OnSampleCompleted(std::vector<Frame> frames) override {}
+
+  void OnSampleCompleted(std::vector<Frame> frames,
+                         TimeTicks sample_timestamp) override {
+    last_timestamp_ = sample_timestamp;
+  }
+
   void OnProfileCompleted(TimeDelta profile_duration,
                           TimeDelta sampling_period) override {}
 
+  TimeTicks last_timestamp() { return last_timestamp_; }
+
  private:
   ModuleCache* module_cache_;
+  TimeTicks last_timestamp_;
 };
 
 // A stack copier for use in tests that provides the expected behavior when
 // operating on the supplied fake stack.
 class TestStackCopier : public StackCopier {
  public:
-  TestStackCopier(const std::vector<uintptr_t>& fake_stack)
-      : fake_stack_(fake_stack) {}
+  TestStackCopier(const std::vector<uintptr_t>& fake_stack,
+                  TimeTicks timestamp = TimeTicks())
+      : fake_stack_(fake_stack), timestamp_(timestamp) {}
 
   bool CopyStack(StackBuffer* stack_buffer,
                  uintptr_t* stack_top,
                  ProfileBuilder* profile_builder,
+                 TimeTicks* timestamp,
                  RegisterContext* thread_context) override {
     std::memcpy(stack_buffer->buffer(), &fake_stack_[0], fake_stack_.size());
     *stack_top =
         reinterpret_cast<uintptr_t>(&fake_stack_[0] + fake_stack_.size());
     // Set the stack pointer to be consistent with the provided fake stack.
+    *thread_context = {};
     RegisterContextStackPointer(thread_context) =
         reinterpret_cast<uintptr_t>(&fake_stack_[0]);
 
+    *timestamp = timestamp_;
+
     return true;
   }
 
@@ -70,6 +83,8 @@
   // Must be a reference to retain the underlying allocation from the vector
   // passed to the constructor.
   const std::vector<uintptr_t>& fake_stack_;
+
+  const TimeTicks timestamp_;
 };
 
 // Trivial unwinder implementation for testing.
@@ -225,6 +240,24 @@
   EXPECT_EQ(stack, stack_copy);
 }
 
+TEST(StackSamplerImplTest, CopyStackTimestamp) {
+  ModuleCache module_cache;
+  const std::vector<uintptr_t> stack = {0};
+  InjectModuleForContextInstructionPointer(stack, &module_cache);
+  std::vector<uintptr_t> stack_copy;
+  TimeTicks timestamp = TimeTicks::UnixEpoch();
+  StackSamplerImpl stack_sampler_impl(
+      std::make_unique<TestStackCopier>(stack, timestamp),
+      std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache);
+
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
+  TestProfileBuilder profile_builder(&module_cache);
+  stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder);
+
+  EXPECT_EQ(timestamp, profile_builder.last_timestamp());
+}
+
 TEST(StackSamplerImplTest, WalkStack_Completed) {
   ModuleCache module_cache;
   RegisterContext thread_context;
diff --git a/base/profiler/stack_sampling_profiler_test_util.cc b/base/profiler/stack_sampling_profiler_test_util.cc
index 8aed9b2..136d21d 100644
--- a/base/profiler/stack_sampling_profiler_test_util.cc
+++ b/base/profiler/stack_sampling_profiler_test_util.cc
@@ -37,7 +37,8 @@
   ModuleCache* GetModuleCache() override { return module_cache_; }
   void RecordMetadata(MetadataProvider* metadata_provider) override {}
 
-  void OnSampleCompleted(std::vector<Frame> sample) override {
+  void OnSampleCompleted(std::vector<Frame> sample,
+                         TimeTicks sample_timestamp) override {
     EXPECT_TRUE(sample_.empty());
     sample_ = std::move(sample);
   }
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
index 87d54002..383da75 100644
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -174,7 +174,8 @@
   ModuleCache* GetModuleCache() override;
   void RecordMetadata(
       ProfileBuilder::MetadataProvider* metadata_provider) override;
-  void OnSampleCompleted(std::vector<Frame> sample) override;
+  void OnSampleCompleted(std::vector<Frame> sample,
+                         TimeTicks sample_timestamp) override;
   void OnProfileCompleted(TimeDelta profile_duration,
                           TimeDelta sampling_period) override;
 
@@ -208,7 +209,8 @@
   ++metadata_count_;
 }
 
-void TestProfileBuilder::OnSampleCompleted(std::vector<Frame> sample) {
+void TestProfileBuilder::OnSampleCompleted(std::vector<Frame> sample,
+                                           TimeTicks sample_timestamp) {
   samples_.push_back(std::move(sample));
 }
 
diff --git a/base/sys_byteorder.h b/base/sys_byteorder.h
index 9ee1827e..93b0d14 100644
--- a/base/sys_byteorder.h
+++ b/base/sys_byteorder.h
@@ -13,7 +13,6 @@
 
 #include <stdint.h>
 
-#include "base/logging.h"
 #include "build/build_config.h"
 
 #if defined(COMPILER_MSVC)
@@ -53,13 +52,11 @@
   // because these conditionals are constexprs, the irrelevant branches will
   // likely be optimized away, so this construction should not result in code
   // bloat.
-  if (sizeof(uintptr_t) == 4) {
+  static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
+                "Unsupported uintptr_t size");
+  if (sizeof(uintptr_t) == 4)
     return ByteSwap(static_cast<uint32_t>(x));
-  } else if (sizeof(uintptr_t) == 8) {
-    return ByteSwap(static_cast<uint64_t>(x));
-  } else {
-    NOTREACHED();
-  }
+  return ByteSwap(static_cast<uint64_t>(x));
 }
 
 // Converts the bytes in |x| from host order (endianness) to little endian, and
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 494100f..e824a84 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/environment.h"
+#include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
@@ -465,10 +466,47 @@
   int exit_code;
 };
 
+// Returns true if child test processes should have dedicated temporary
+// directories.
+constexpr bool SupportsPerChildTempDirs() {
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  return true;
+#else
+  // TODO(https://crbug.com/1038857): Enable for Linux and Fuchsia.
+  return false;
+#endif
+}
+
+// Returns the path to a temporary directory within |task_temp_dir| for the
+// child process of index |child_index|, or an empty FilePath if per-child temp
+// dirs are not supported.
+FilePath CreateChildTempDirIfSupported(const FilePath& task_temp_dir,
+                                       int child_index) {
+  if (!SupportsPerChildTempDirs())
+    return FilePath();
+  FilePath child_temp = task_temp_dir.AppendASCII(NumberToString(child_index));
+  CHECK(CreateDirectoryAndGetError(child_temp, nullptr));
+  return child_temp;
+}
+
+// Adds the platform-specific variable setting |temp_dir| as a process's
+// temporary directory to |environment|.
+void SetTemporaryDirectory(const FilePath& temp_dir,
+                           EnvironmentMap* environment) {
+#if defined(OS_WIN)
+  environment->emplace(L"TMP", temp_dir.value());
+#elif defined(OS_MACOSX)
+  environment->emplace("MAC_CHROMIUM_TMPDIR", temp_dir.value());
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+  environment->emplace("TMPDIR", temp_dir.value());
+#endif
+}
+
 // This launches the child test process, waits for it to complete,
 // and returns child process results.
 ChildProcessResults DoLaunchChildTestProcess(
     const CommandLine& command_line,
+    const FilePath& process_temp_dir,
     TimeDelta timeout,
     const TestLauncher::LaunchOptions& test_launch_options,
     bool redirect_stdio,
@@ -486,6 +524,10 @@
   }
 
   LaunchOptions options;
+
+  // Tell the child process to use its designated temporary directory.
+  if (!process_temp_dir.empty())
+    SetTemporaryDirectory(process_temp_dir, &options.environment);
 #if defined(OS_WIN)
 
   options.inherit_mode = test_launch_options.inherit_mode;
@@ -581,25 +623,26 @@
  private:
   // Called to check if the next batch has to run on the same
   // sequence task runner and using the same temporary directory.
-  bool ShouldReuseStateFromLastBatch(
+  static bool ShouldReuseStateFromLastBatch(
       const std::vector<std::string>& test_names) {
     return test_names.size() == 1u &&
            test_names.front().find(kPreTestPrefix) != std::string::npos;
   }
 
-  // Launch next child process on |task_runner|,
-  // and clear |temp_dir| from previous process.
-  void LaunchNextTask(scoped_refptr<TaskRunner> task_runner, FilePath temp_dir);
+  // Launches the next child process on |task_runner| and clears
+  // |last_task_temp_dir| from the previous task.
+  void LaunchNextTask(scoped_refptr<TaskRunner> task_runner,
+                      const FilePath& last_task_temp_dir);
 
-  // Forward |temp_dir| and Launch next task on main thread.
+  // Forwards |last_task_temp_dir| and launches the next task on main thread.
   // The method is called on |task_runner|.
   void ClearAndLaunchNext(scoped_refptr<TaskRunner> main_thread_runner,
                           scoped_refptr<TaskRunner> task_runner,
-                          const FilePath& temp_dir) {
+                          const FilePath& last_task_temp_dir) {
     main_thread_runner->PostTask(
         FROM_HERE,
         BindOnce(&TestRunner::LaunchNextTask, weak_ptr_factory_.GetWeakPtr(),
-                 task_runner, temp_dir));
+                 task_runner, last_task_temp_dir));
   }
 
   ThreadChecker thread_checker_;
@@ -639,12 +682,13 @@
 }
 
 void TestRunner::LaunchNextTask(scoped_refptr<TaskRunner> task_runner,
-                                FilePath temp_dir) {
+                                const FilePath& last_task_temp_dir) {
   DCHECK(thread_checker_.CalledOnValidThread());
   // delete previous temporary directory
-  if (!temp_dir.empty() && !DeleteFileRecursively(temp_dir)) {
+  if (!last_task_temp_dir.empty() &&
+      !DeleteFileRecursively(last_task_temp_dir)) {
     // This needs to be non-fatal at least for Windows.
-    LOG(WARNING) << "Failed to delete " << temp_dir.AsUTF8Unsafe();
+    LOG(WARNING) << "Failed to delete " << last_task_temp_dir.AsUTF8Unsafe();
   }
 
   // No more tests to run, finish sequence.
@@ -656,10 +700,17 @@
     return;
   }
 
-  CreateNewTempDirectory(FilePath::StringType(), &temp_dir);
+  // Create a temporary directory for this task. This directory will hold the
+  // flags and results files for the child processes as well as their User Data
+  // dir, where appropriate. For platforms that support per-child temp dirs,
+  // this directory will also contain one subdirectory per child for that
+  // child's process-wide temp dir.
+  base::FilePath task_temp_dir;
+  CHECK(CreateNewTempDirectory(FilePath::StringType(), &task_temp_dir));
   bool post_to_current_runner = true;
   size_t batch_size = (batch_size_ == 0) ? tests_to_run_.size() : batch_size_;
 
+  int child_index = 0;
   while (post_to_current_runner && !tests_to_run_.empty()) {
     batch_size = std::min(batch_size, tests_to_run_.size());
     std::vector<std::string> batch(tests_to_run_.rbegin(),
@@ -668,13 +719,29 @@
     task_runner->PostTask(
         FROM_HERE,
         BindOnce(&TestLauncher::LaunchChildGTestProcess, Unretained(launcher_),
-                 ThreadTaskRunnerHandle::Get(), batch, temp_dir));
+                 ThreadTaskRunnerHandle::Get(), batch, task_temp_dir,
+                 CreateChildTempDirIfSupported(task_temp_dir, child_index++)));
     post_to_current_runner = ShouldReuseStateFromLastBatch(batch);
   }
   task_runner->PostTask(
       FROM_HERE,
       BindOnce(&TestRunner::ClearAndLaunchNext, Unretained(this),
-               ThreadTaskRunnerHandle::Get(), task_runner, temp_dir));
+               ThreadTaskRunnerHandle::Get(), task_runner, task_temp_dir));
+}
+
+// Returns the number of files and directories in |dir|, or 0 if |dir| is empty.
+int CountItemsInDirectory(const FilePath& dir) {
+  if (dir.empty())
+    return 0;
+  int items = 0;
+  FileEnumerator file_enumerator(
+      dir, /*recursive=*/false,
+      FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
+  for (FilePath name = file_enumerator.Next(); !name.empty();
+       name = file_enumerator.Next()) {
+    ++items;
+  }
+  return items;
 }
 
 }  // namespace
@@ -868,10 +935,11 @@
 void TestLauncher::LaunchChildGTestProcess(
     scoped_refptr<TaskRunner> task_runner,
     const std::vector<std::string>& test_names,
-    const FilePath& temp_dir) {
+    const FilePath& task_temp_dir,
+    const FilePath& child_temp_dir) {
   FilePath result_file;
-  CommandLine cmd_line =
-      launcher_delegate_->GetCommandLine(test_names, temp_dir, &result_file);
+  CommandLine cmd_line = launcher_delegate_->GetCommandLine(
+      test_names, task_temp_dir, &result_file);
 
   // Record the exact command line used to launch the child.
   CommandLine new_command_line(
@@ -880,8 +948,9 @@
   options.flags = launcher_delegate_->GetLaunchOptions();
 
   ChildProcessResults process_results = DoLaunchChildTestProcess(
-      new_command_line, launcher_delegate_->GetTimeout() * test_names.size(),
-      options, redirect_stdio_, launcher_delegate_);
+      new_command_line, child_temp_dir,
+      launcher_delegate_->GetTimeout() * test_names.size(), options,
+      redirect_stdio_, launcher_delegate_);
 
   // Invoke ProcessTestResults on the original thread, not
   // on a worker pool thread.
@@ -890,7 +959,8 @@
       BindOnce(&TestLauncher::ProcessTestResults, Unretained(this), test_names,
                result_file, process_results.output_file_contents,
                process_results.elapsed_time, process_results.exit_code,
-               process_results.was_timeout));
+               process_results.was_timeout,
+               CountItemsInDirectory(child_temp_dir)));
 }
 
 // Determines which result status will be assigned for missing test results.
@@ -920,7 +990,8 @@
     const std::string& output,
     TimeDelta elapsed_time,
     int exit_code,
-    bool was_timeout) {
+    bool was_timeout,
+    int leaked_items) {
   std::vector<TestResult> test_results;
   bool crashed = false;
   bool have_test_results =
@@ -1000,6 +1071,9 @@
     i.output_snippet = GetTestOutputSnippet(i, output);
   }
 
+  if (leaked_items)
+    results_tracker_.AddLeakedItems(leaked_items, test_names);
+
   launcher_delegate_->ProcessTestResults(final_results, elapsed_time);
 
   for (const auto& result : final_results)
diff --git a/base/test/launcher/test_launcher.h b/base/test/launcher/test_launcher.h
index 908f103..3100bc3 100644
--- a/base/test/launcher/test_launcher.h
+++ b/base/test/launcher/test_launcher.h
@@ -135,14 +135,17 @@
 
   // Launches a child process (assumed to be gtest-based binary) which runs
   // tests indicated by |test_names|.
-  // |task_runner| is used to post results back to the launcher
-  // on the main thread. |temp_dir| is used for child process files,
-  // such as user data, result file, and flag_file.
+  // |task_runner| is used to post results back to the launcher on the main
+  // thread. |task_temp_dir| is used for child process files such as user data,
+  // result file, and flag_file. |child_temp_dir|, if not empty, specifies a
+  // directory (within task_temp_dir) that the child process will use as its
+  // process-wide temporary directory.
   // virtual to mock in testing.
   virtual void LaunchChildGTestProcess(
       scoped_refptr<TaskRunner> task_runner,
       const std::vector<std::string>& test_names,
-      const FilePath& temp_dir);
+      const FilePath& task_temp_dir,
+      const FilePath& child_temp_dir);
 
   // Called when a test has finished running.
   void OnTestFinished(const TestResult& result);
@@ -206,12 +209,15 @@
   // EXPECT/ASSERT/DCHECK statements. Test launcher parses that
   // file to get additional information about test run (status,
   // error-messages, stack-traces and file/line for failures).
+  // |leaked_items| is the number of files and/or directories remaining in the
+  // child process's temporary directory upon its termination.
   void ProcessTestResults(const std::vector<std::string>& test_names,
                           const FilePath& result_file,
                           const std::string& output,
                           TimeDelta elapsed_time,
                           int exit_code,
-                          bool was_timeout);
+                          bool was_timeout,
+                          int leaked_items);
 
   // Make sure we don't accidentally call the wrong methods e.g. on the worker
   // pool thread.  Should be the first member so that it's destroyed last: when
diff --git a/base/test/launcher/test_launcher_unittest.cc b/base/test/launcher/test_launcher_unittest.cc
index 0f70a643..641b98d 100644
--- a/base/test/launcher/test_launcher_unittest.cc
+++ b/base/test/launcher/test_launcher_unittest.cc
@@ -65,10 +65,11 @@
 
   void CreateAndStartThreadPool(int parallel_jobs) override {}
 
-  MOCK_METHOD3(LaunchChildGTestProcess,
+  MOCK_METHOD4(LaunchChildGTestProcess,
                void(scoped_refptr<TaskRunner> task_runner,
                     const std::vector<std::string>& test_names,
-                    const FilePath& temp_dir));
+                    const FilePath& task_temp_dir,
+                    const FilePath& child_temp_dir));
 };
 
 // Simple TestLauncherDelegate mock to test TestLauncher flow.
@@ -185,7 +186,7 @@
 TEST_F(TestLauncherTest, EmptyTestSetPasses) {
   SetUpExpectCalls();
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _)).Times(0);
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _)).Times(0);
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
 }
 
@@ -201,7 +202,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(::testing::DoAll(OnTestResult(&test_launcher, "Test.firstTest",
                                               TestResult::TEST_SUCCESS),
                                  OnTestResult(&test_launcher, "Test.secondTest",
@@ -220,7 +221,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .Times(1);
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
 }
@@ -237,7 +238,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.firstTest",
                              TestResult::TEST_SUCCESS));
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
@@ -255,7 +256,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .Times(1);
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
 }
@@ -266,7 +267,7 @@
   SetUpExpectCalls();
   command_line->AppendSwitchASCII("gtest_repeat", "2");
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _))
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
       .Times(2)
       .WillRepeatedly(OnTestResult(&test_launcher, "Test.firstTest",
                                    TestResult::TEST_SUCCESS));
@@ -284,7 +285,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.firstTest",
                              TestResult::TEST_FAILURE))
       .WillOnce(OnTestResult(&test_launcher, "Test.firstTest",
@@ -304,7 +305,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .Times(3)
       .WillRepeatedly(OnTestResult(&test_launcher, "Test.firstTest",
                                    TestResult::TEST_FAILURE));
@@ -321,7 +322,7 @@
       GenerateTestResult("Test.PRE_firstTest", TestResult::TEST_FAILURE),
       GenerateTestResult("Test.firstTest", TestResult::TEST_SUCCESS)};
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _))
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
       .WillOnce(::testing::DoAll(
           OnTestResult(&test_launcher, "Test.PRE_PRE_firstTest",
                        TestResult::TEST_SUCCESS),
@@ -334,7 +335,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.PRE_PRE_firstTest",
                              TestResult::TEST_SUCCESS));
   tests_names = {"Test.PRE_firstTest"};
@@ -342,7 +343,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.PRE_firstTest",
                              TestResult::TEST_SUCCESS));
   tests_names = {"Test.firstTest"};
@@ -350,7 +351,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.firstTest",
                              TestResult::TEST_SUCCESS));
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
@@ -372,7 +373,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .WillOnce(::testing::DoAll(
           OnTestResult(&test_launcher, "Test.firstTest",
                        TestResult::TEST_SUCCESS),
@@ -394,7 +395,7 @@
                                  _,
                                  testing::ElementsAreArray(tests_names.cbegin(),
                                                            tests_names.cend()),
-                                 _))
+                                 _, _))
       .Times(1);
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
 }
@@ -412,7 +413,7 @@
   SetUpExpectCalls();
   command_line->AppendSwitchASCII("test-launcher-print-test-stdio", "always");
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _))
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
       .WillOnce(OnTestResult(&test_launcher, "Test.firstTest",
                              TestResult::TEST_SUCCESS));
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
@@ -524,7 +525,7 @@
                          TimeDelta::FromMilliseconds(50), "output_second");
 
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _))
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
       .Times(2)
       .WillRepeatedly(
           ::testing::DoAll(OnTestResult(&test_launcher, first_result),
@@ -580,7 +581,7 @@
                          TimeDelta::FromMilliseconds(50), "output_second");
 
   using ::testing::_;
-  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _))
+  EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
       .WillOnce(OnTestResult(&test_launcher, test_result));
   EXPECT_TRUE(test_launcher.Run(command_line.get()));
 
diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc
index 8522db4..37c31ac3 100644
--- a/base/test/launcher/test_results_tracker.cc
+++ b/base/test/launcher/test_results_tracker.cc
@@ -22,6 +22,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/gtest_util.h"
 #include "base/test/launcher/test_launcher.h"
+#include "base/test/test_switches.h"
 #include "base/time/time.h"
 #include "base/values.h"
 
@@ -166,6 +167,9 @@
     return false;
   }
 
+  print_temp_leaks_ =
+      command_line.HasSwitch(switches::kTestLauncherPrintTempLeaks);
+
   if (!command_line.HasSwitch(kGTestOutputFlag))
     return true;
 
@@ -270,6 +274,13 @@
   aggregate_test_result.test_results.push_back(result);
 }
 
+void TestResultsTracker::AddLeakedItems(
+    int count,
+    const std::vector<std::string>& test_names) {
+  DCHECK(count);
+  per_iteration_data_.back().leaked_temp_items.emplace_back(count, test_names);
+}
+
 void TestResultsTracker::GeneratePlaceholderIteration() {
   CHECK(thread_checker_.CalledOnValidThread());
 
@@ -316,6 +327,13 @@
              "had unknown result");
   PrintTests(tests_by_status[TestResult::TEST_NOT_RUN].begin(),
              tests_by_status[TestResult::TEST_NOT_RUN].end(), "not run");
+
+  if (print_temp_leaks_) {
+    for (const auto& leaking_tests :
+         per_iteration_data_.back().leaked_temp_items) {
+      PrintLeaks(leaking_tests.first, leaking_tests.second);
+    }
+  }
 }
 
 void TestResultsTracker::PrintSummaryOfAllIterations() const {
@@ -574,6 +592,16 @@
   fflush(stdout);
 }
 
+void TestResultsTracker::PrintLeaks(
+    int count,
+    const std::vector<std::string>& test_names) const {
+  fprintf(stdout,
+          "ERROR: %d files and/or directories were left behind in the temporary"
+          " directory by one or more of these tests: %s\n",
+          count, JoinString(test_names, ":").c_str());
+  fflush(stdout);
+}
+
 TestResultsTracker::AggregateTestResult::AggregateTestResult() = default;
 
 TestResultsTracker::AggregateTestResult::AggregateTestResult(
diff --git a/base/test/launcher/test_results_tracker.h b/base/test/launcher/test_results_tracker.h
index 61f29cd..7201ab48 100644
--- a/base/test/launcher/test_results_tracker.h
+++ b/base/test/launcher/test_results_tracker.h
@@ -61,6 +61,10 @@
   // Adds |result| to the stored test results.
   void AddTestResult(const TestResult& result);
 
+  // Adds to the current iteration the fact that |count| items were leaked by
+  // one or more tests in |test_names| in its temporary directory.
+  void AddLeakedItems(int count, const std::vector<std::string>& test_names);
+
   // Even when no iterations have occurred, we still want to generate output
   // data with "NOTRUN" status for each test. This method generates a
   // placeholder iteration. The first iteration will overwrite the data in the
@@ -101,6 +105,7 @@
   void PrintTests(InputIterator first,
                   InputIterator last,
                   const std::string& description) const;
+  void PrintLeaks(int count, const std::vector<std::string>& test_names) const;
 
   struct AggregateTestResult {
     AggregateTestResult();
@@ -118,6 +123,9 @@
     // Aggregate test results grouped by full test name.
     typedef std::map<std::string, AggregateTestResult> ResultsMap;
     ResultsMap results;
+
+    // A sequence of tests that leaked files/dirs in their temp directory.
+    std::vector<std::pair<int, std::vector<std::string>>> leaked_temp_items;
   };
 
   struct CodeLocation {
@@ -130,6 +138,9 @@
 
   ThreadChecker thread_checker_;
 
+  // Print tests that leak files and/or directories in their temp dir.
+  bool print_temp_leaks_ = false;
+
   // Set of global tags, i.e. strings indicating conditions that apply to
   // the entire test run.
   std::set<std::string> global_tags_;
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc
index 039a69c..ec0800c 100644
--- a/base/test/launcher/unit_test_launcher.cc
+++ b/base/test/launcher/unit_test_launcher.cc
@@ -104,7 +104,11 @@
           "    Sets the shard index to run to N (from 0 to TOTAL - 1).\n"
           "\n"
           "  --dont-use-job-objects\n"
-          "    Avoids using job objects in Windows.\n");
+          "    Avoids using job objects in Windows.\n"
+          "\n"
+          "  --test-launcher-print-temp-leaks\n"
+          "    Prints information about leaked files and/or directories in\n"
+          "    child process's temporary directories (Windows and macOS).\n");
   fflush(stdout);
 }
 
diff --git a/base/test/test_switches.cc b/base/test/test_switches.cc
index f1d04d5..ec022ced 100644
--- a/base/test/test_switches.cc
+++ b/base/test/test_switches.cc
@@ -58,6 +58,11 @@
 const char switches::kTestLauncherSummaryOutput[] =
     "test-launcher-summary-output";
 
+// Causes the test launcher to print information about leaked files and/or
+// directories in child process's temporary directories.
+const char switches::kTestLauncherPrintTempLeaks[] =
+    "test-launcher-print-temp-leaks";
+
 // Flag controlling when test stdio is displayed as part of the launcher's
 // standard output.
 const char switches::kTestLauncherPrintTestStdio[] =
diff --git a/base/test/test_switches.h b/base/test/test_switches.h
index 2d6b5f4..9e2e627 100644
--- a/base/test/test_switches.h
+++ b/base/test/test_switches.h
@@ -25,6 +25,7 @@
 extern const char kTestLauncherRetryLimit[];
 extern const char kIsolatedScriptTestLauncherRetryLimit[];
 extern const char kTestLauncherSummaryOutput[];
+extern const char kTestLauncherPrintTempLeaks[];
 extern const char kTestLauncherPrintTestStdio[];
 extern const char kTestLauncherPrintWritablePath[];
 extern const char kTestLauncherShardIndex[];
diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h
index 57ac025..d6eb35c 100644
--- a/base/trace_event/common/trace_event_common.h
+++ b/base/trace_event/common/trace_event_common.h
@@ -1079,7 +1079,6 @@
 #define TRACE_EVENT_PHASE_CLOCK_SYNC ('c')
 #define TRACE_EVENT_PHASE_ENTER_CONTEXT ('(')
 #define TRACE_EVENT_PHASE_LEAVE_CONTEXT (')')
-#define TRACE_EVENT_PHASE_LINK_IDS ('=')
 
 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
 #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index df910294..0ced0e5d 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -407,23 +407,6 @@
     }                                                                        \
   } while (0)
 
-// The linked ID will not be mangled.
-#define INTERNAL_TRACE_EVENT_ADD_LINK_IDS(category_group, name, id1, id2) \
-  do {                                                                    \
-    INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);               \
-    if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                  \
-      trace_event_internal::TraceID source_id((id1));                     \
-      unsigned int source_flags = source_id.id_flags();                   \
-      trace_event_internal::TraceID target_id((id2));                     \
-      trace_event_internal::AddTraceEvent(                                \
-          TRACE_EVENT_PHASE_LINK_IDS,                                     \
-          INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,         \
-          source_id.scope(), source_id.raw_id(), source_flags,            \
-          trace_event_internal::kNoId, "linked_id",                       \
-          target_id.AsConvertableToTraceFormat());                        \
-    }                                                                     \
-  } while (0)
-
 // Implementation detail: internal macro to create static category and add
 // metadata event if the category is enabled.
 #define INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, ...) \
@@ -635,9 +618,6 @@
   unsigned long long prefix() const { return prefix_; }
   unsigned int id_flags() const { return id_flags_; }
 
-  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
-  AsConvertableToTraceFormat() const;
-
  private:
   const char* scope_ = nullptr;
   bool has_prefix_ = false;
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 04cf3840..c74d71c 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -311,42 +311,3 @@
 
 }  // namespace trace_event
 }  // namespace base
-
-namespace trace_event_internal {
-
-std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
-TraceID::AsConvertableToTraceFormat() const {
-  auto value = std::make_unique<base::trace_event::TracedValue>();
-
-  if (scope_ != kGlobalScope)
-    value->SetString("scope", scope_);
-
-  const char* id_field_name = "id";
-  if (id_flags_ == TRACE_EVENT_FLAG_HAS_GLOBAL_ID) {
-    id_field_name = "global";
-    value->BeginDictionary("id2");
-  } else if (id_flags_ == TRACE_EVENT_FLAG_HAS_LOCAL_ID) {
-    id_field_name = "local";
-    value->BeginDictionary("id2");
-  } else if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID) {
-    NOTREACHED() << "Unrecognized ID flag";
-  }
-
-  if (has_prefix_) {
-    value->SetString(id_field_name,
-                     base::StringPrintf("0x%" PRIx64 "/0x%" PRIx64,
-                                        static_cast<uint64_t>(prefix_),
-                                        static_cast<uint64_t>(raw_id_)));
-  } else {
-    value->SetString(
-        id_field_name,
-        base::StringPrintf("0x%" PRIx64, static_cast<uint64_t>(raw_id_)));
-  }
-
-  if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID)
-    value->EndDictionary();
-
-  return std::move(value);
-}
-
-}  // namespace trace_event_internal
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index 0d9405b..de86bcf 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -7,11 +7,13 @@
 """Adds the code parts to a resource APK."""
 
 import argparse
+import logging
 import os
 import shutil
 import sys
 import tempfile
 import zipfile
+import zlib
 
 import finalize_apk
 
@@ -99,6 +101,12 @@
                       help='Keystore password')
   parser.add_argument('--key-name',
                       help='Keystore name')
+  parser.add_argument(
+      '--min-sdk-version', required=True, help='Value of APK\'s minSdkVersion')
+  parser.add_argument(
+      '--best-compression',
+      action='store_true',
+      help='Use zip -9 rather than zip -1')
   options = parser.parse_args(args)
   options.assets = build_utils.ParseGnList(options.assets)
   options.uncompressed_assets = build_utils.ParseGnList(
@@ -173,7 +181,7 @@
   return ret
 
 
-def _AddAssets(apk, path_tuples, disable_compression=False):
+def _AddAssets(apk, path_tuples, fast_align, disable_compression=False):
   """Adds the given paths to the apk.
 
   Args:
@@ -185,10 +193,15 @@
   # locality of mmap'ed files.
   for target_compress in (False, True):
     for src_path, dest_path in path_tuples:
-
       compress = not disable_compression and (
           os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS)
+
       if target_compress == compress:
+        # AddToZipHermetic() uses this logic to avoid growing small files.
+        # We need it here in order to set alignment correctly.
+        if compress and os.path.getsize(src_path) < 16:
+          compress = False
+
         apk_path = 'assets/' + dest_path
         try:
           apk.getinfo(apk_path)
@@ -196,11 +209,16 @@
           raise Exception('Multiple targets specified the asset path: %s' %
                           apk_path)
         except KeyError:
-          build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path,
-                                       compress=compress)
+          zipalign.AddToZipHermetic(
+              apk,
+              apk_path,
+              src_path=src_path,
+              compress=compress,
+              alignment=0 if compress and not fast_align else 4)
 
 
-def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
+def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress,
+                        fast_align):
   """Add native libraries to APK."""
   has_crazy_linker = any(
       'android_linker' in os.path.basename(p) for p in native_libs)
@@ -221,16 +239,33 @@
           basename = 'crazy.' + basename
 
     apk_path = 'lib/%s/%s' % (android_abi, basename)
-    build_utils.AddToZipHermetic(out_apk,
-                                 apk_path,
-                                 src_path=path,
-                                 compress=compress)
+    zipalign.AddToZipHermetic(
+        out_apk,
+        apk_path,
+        src_path=path,
+        compress=compress,
+        alignment=0 if compress and not fast_align else 0x1000)
 
 
 def main(args):
+  build_utils.InitLogging('APKBUILDER_DEBUG')
   args = build_utils.ExpandFileArgs(args)
   options = _ParseArgs(args)
 
+  # Until Python 3.7, there's no better way to set compression level.
+  # The default is 6.
+  if options.best_compression:
+    # Compresses about twice as slow as the default.
+    zlib.Z_DEFAULT_COMPRESSION = 9
+  else:
+    # Compresses about twice as fast as the default.
+    zlib.Z_DEFAULT_COMPRESSION = 1
+
+  # Manually align only when alignment is necessary.
+  # Python's zip implementation duplicates file comments in the central
+  # directory, whereas zipalign does not, so use zipalign for official builds.
+  fast_align = options.format == 'apk' and not options.best_compression
+
   native_libs = sorted(options.native_libs)
 
   # Include native libs in the depfile_deps since GN doesn't know about the
@@ -282,52 +317,56 @@
   # Targets generally do not depend on apks, so no need for only_if_changed.
   with build_utils.AtomicOutput(options.output_apk, only_if_changed=False) as f:
     with zipfile.ZipFile(options.resource_apk) as resource_apk, \
-         zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as out_apk:
+         zipfile.ZipFile(f, 'w') as out_apk:
+
+      def add_to_zip(zip_path, data, compress=True):
+        zipalign.AddToZipHermetic(
+            out_apk,
+            zip_path,
+            data=data,
+            compress=compress,
+            alignment=0 if compress and not fast_align else 4)
 
       def copy_resource(zipinfo, out_dir=''):
-        compress = zipinfo.compress_type != zipfile.ZIP_STORED
-        build_utils.AddToZipHermetic(
-            out_apk,
+        add_to_zip(
             out_dir + zipinfo.filename,
-            data=resource_apk.read(zipinfo.filename),
-            compress=compress)
+            resource_apk.read(zipinfo.filename),
+            compress=zipinfo.compress_type != zipfile.ZIP_STORED)
 
       # Make assets come before resources in order to maintain the same file
       # ordering as GYP / aapt. http://crbug.com/561862
       resource_infos = resource_apk.infolist()
 
       # 1. AndroidManifest.xml
+      logging.debug('Adding AndroidManifest.xml')
       copy_resource(
           resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir)
 
       # 2. Assets
-      _AddAssets(out_apk, assets, disable_compression=False)
-      _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
+      logging.debug('Adding assets/')
+      _AddAssets(out_apk, assets, fast_align, disable_compression=False)
+      _AddAssets(
+          out_apk, uncompressed_assets, fast_align, disable_compression=True)
 
       # 3. Dex files
-      if options.dex_file and options.dex_file.endswith('.zip'):
+      logging.debug('Adding classes.dex')
+      if options.dex_file:
         with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
           for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
-            build_utils.AddToZipHermetic(
-                out_apk,
+            add_to_zip(
                 apk_dex_dir + dex,
-                data=dex_zip.read(dex),
+                dex_zip.read(dex),
                 compress=not options.uncompress_dex)
-      elif options.dex_file:
-        build_utils.AddToZipHermetic(
-            out_apk,
-            apk_dex_dir + 'classes.dex',
-            src_path=options.dex_file,
-            compress=not options.uncompress_dex)
 
       # 4. Native libraries.
+      logging.debug('Adding lib/')
       _AddNativeLibraries(out_apk, native_libs, options.android_abi,
-                          options.uncompress_shared_libraries)
+                          options.uncompress_shared_libraries, fast_align)
 
       if options.secondary_android_abi:
         _AddNativeLibraries(out_apk, secondary_native_libs,
                             options.secondary_android_abi,
-                            options.uncompress_shared_libraries)
+                            options.uncompress_shared_libraries, fast_align)
 
       # Add a placeholder lib if the APK should be multi ABI but is missing libs
       # for one of the ABIs.
@@ -349,16 +388,17 @@
         # with stale builds when the only change is adding/removing
         # placeholders).
         apk_path = 'lib/%s/%s' % (options.android_abi, name)
-        build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+        add_to_zip(apk_path, '')
 
       for name in sorted(secondary_native_lib_placeholders):
         # Note: Empty libs files are ignored by md5check (can cause issues
         # with stale builds when the only change is adding/removing
         # placeholders).
         apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
-        build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+        add_to_zip(apk_path, '')
 
       # 5. Resources
+      logging.debug('Adding res/')
       for info in sorted(resource_infos, key=lambda i: i.filename):
         if info.filename != 'AndroidManifest.xml':
           copy_resource(info)
@@ -366,6 +406,7 @@
       # 6. Java resources that should be accessible via
       # Class.getResourceAsStream(), in particular parts of Emma jar.
       # Prebuilt jars may contain class files which we shouldn't include.
+      logging.debug('Adding Java resources')
       for java_resource in options.java_resources:
         with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
           for apk_path in sorted(java_resource_jar.namelist()):
@@ -378,15 +419,15 @@
             if apk_path_lower.endswith('.class'):
               continue
 
-            build_utils.AddToZipHermetic(
-                out_apk,
-                apk_root_dir + apk_path,
-                data=java_resource_jar.read(apk_path))
+            add_to_zip(apk_root_dir + apk_path,
+                       java_resource_jar.read(apk_path))
 
     if options.format == 'apk':
-      finalize_apk.FinalizeApk(options.apksigner_jar, options.zipalign_path,
-                               f.name, f.name, options.key_path,
-                               options.key_passwd, options.key_name)
+      zipalign_path = None if fast_align else options.zipalign_path
+      finalize_apk.FinalizeApk(options.apksigner_jar, zipalign_path, f.name,
+                               f.name, options.key_path, options.key_passwd,
+                               options.key_name, int(options.min_sdk_version))
+    logging.debug('Moving file into place')
 
   if options.depfile:
     build_utils.WriteDepfile(
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py
index b6be025..f338633 100644
--- a/build/android/gyp/finalize_apk.py
+++ b/build/android/gyp/finalize_apk.py
@@ -4,6 +4,7 @@
 """Signs and aligns an APK."""
 
 import argparse
+import logging
 import shutil
 import subprocess
 import tempfile
@@ -12,21 +13,28 @@
 
 
 def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path,
-                final_apk_path, key_path, key_passwd, key_name):
+                final_apk_path, key_path, key_passwd, key_name,
+                min_sdk_version):
   # Use a tempfile so that Ctrl-C does not leave the file with a fresh mtime
   # and a corrupted state.
   with tempfile.NamedTemporaryFile() as staging_file:
-    # v2 signing requires that zipalign happen first.
-    subprocess.check_output([
-        zipalign_path, '-p', '-f', '4',
-        unsigned_apk_path, staging_file.name])
-    subprocess.check_output([
+    if zipalign_path:
+      # v2 signing requires that zipalign happen first.
+      logging.debug('Running zipalign')
+      subprocess.check_output([
+          zipalign_path, '-p', '-f', '4', unsigned_apk_path, staging_file.name
+      ])
+      signer_input_path = staging_file.name
+    else:
+      signer_input_path = unsigned_apk_path
+
+    sign_cmd = [
         build_utils.JAVA_PATH,
         '-jar',
         apksigner_path,
         'sign',
         '--in',
-        staging_file.name,
+        signer_input_path,
         '--out',
         staging_file.name,
         '--ks',
@@ -35,9 +43,21 @@
         key_name,
         '--ks-pass',
         'pass:' + key_passwd,
-        # Force SHA-1 (makes signing faster; insecure is fine for local builds).
-        '--min-sdk-version',
-        '1',
-    ])
+    ]
+    # V3 signing adds security niceties, which are irrelevant for local builds.
+    sign_cmd += ['--v3-signing-enabled', 'false']
+
+    if min_sdk_version >= 24:
+      # Disable v1 signatures when v2 signing can be used (it's much faster).
+      # By default, both v1 and v2 signing happen.
+      sign_cmd += ['--v1-signing-enabled', 'false']
+    else:
+      # Force SHA-1 (makes signing faster; insecure is fine for local builds).
+      # Leave v2 signing enabled since it verifies faster on device when
+      # supported.
+      sign_cmd += ['--min-sdk-version', '1']
+
+    logging.debug('Signing apk')
+    subprocess.check_call(sign_cmd)
     shutil.move(staging_file.name, final_apk_path)
     staging_file.delete = False
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index dfae1db..fa5ad3cbe 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -216,12 +216,8 @@
     # from failing.
     build_utils.Touch(tmp_mapping_path)
 
-    output_is_zipped = not options.output_path.endswith('.dex')
     tmp_output = os.path.join(tmp_dir, 'r8out')
-    if output_is_zipped:
-      tmp_output += '.jar'
-    else:
-      os.mkdir(tmp_output)
+    os.mkdir(tmp_output)
 
     cmd = [
         build_utils.JAVA_PATH,
@@ -265,14 +261,17 @@
           'android/docs/java_optimization.md#Debugging-common-failures\n'))
       raise ProguardProcessError(err, debugging_link)
 
-    if not output_is_zipped:
-      found_files = os.listdir(tmp_output)
+    found_files = build_utils.FindInDirectory(tmp_output)
+    if not options.output_path.endswith('.dex'):
+      # Add to .jar using Python rather than having R8 output to a .zip directly
+      # in order to disable compression of the .jar, saving ~500ms.
+      tmp_jar_output = tmp_output + '.jar'
+      build_utils.DoZip(found_files, tmp_jar_output, base_dir=tmp_output)
+      shutil.move(tmp_jar_output, options.output_path)
+    else:
       if len(found_files) > 1:
         raise Exception('Too many files created: {}'.format(found_files))
-      tmp_output = os.path.join(tmp_output, found_files[0])
-
-    # Copy output files to correct locations.
-    shutil.move(tmp_output, options.output_path)
+      shutil.move(found_files[0], options.output_path)
 
     with open(options.mapping_output, 'w') as out_file, \
         open(tmp_mapping_path) as in_file:
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 75e7144..e0d5e1a 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1870,19 +1870,16 @@
   #     variables and an onResourcesLoaded() method.
   #
   # Output variables:
-  #   zip_path: (optional)
+  #   resources_zip:
   #     Path to a .resources.zip that will simply contain all the
   #     input resources, collected in a single archive.
   #
-  #   r_text_out_path: (optional): Path for the generated R.txt file.
+  #   r_text_out_path: Path for the generated R.txt file.
   #
   #   srcjar_path: (optional) Path to a generated .srcjar containing the
   #                           generated R.java source file.
   #
   template("prepare_resources") {
-    if (defined(invoker.srcjar_path)) {
-      _srcjar_path = invoker.srcjar_path
-    }
     action_with_pydeps(target_name) {
       set_sources_assignment_filter([])
       forward_variables_from(invoker,
@@ -1895,7 +1892,11 @@
       script = "//build/android/gyp/prepare_resources.py"
 
       depfile = "$target_gen_dir/${invoker.target_name}.d"
-      outputs = []
+      outputs = [
+        invoker.resources_zip,
+        invoker.resources_zip + ".info",
+        invoker.r_text_out_path,
+      ]
 
       _android_aapt_path = android_default_aapt_path
 
@@ -1919,6 +1920,10 @@
         "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)",
         "--extra-r-text-files=@FileArg($_rebased_build_config:deps_info:extra_r_text_files)",
         "--res-sources-path=$_rebased_res_sources_path",
+        "--resource-zip-out",
+        rebase_path(invoker.resources_zip, root_build_dir),
+        "--r-text-out",
+        rebase_path(invoker.r_text_out_path, root_build_dir),
       ]
 
       if (defined(invoker.android_manifest)) {
@@ -1932,30 +1937,11 @@
         ]
       }
 
-      if (defined(invoker.zip_path)) {
-        outputs += [
-          invoker.zip_path,
-          invoker.zip_path + ".info",
-        ]
-        args += [
-          "--resource-zip-out",
-          rebase_path(invoker.zip_path, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.r_text_out_path)) {
-        outputs += [ invoker.r_text_out_path ]
-        args += [
-          "--r-text-out",
-          rebase_path(invoker.r_text_out_path, root_build_dir),
-        ]
-      }
-
-      if (defined(_srcjar_path)) {
-        outputs += [ _srcjar_path ]
+      if (defined(invoker.srcjar_path)) {
+        outputs += [ invoker.srcjar_path ]
         args += [
           "--srcjar-out",
-          rebase_path(_srcjar_path, root_build_dir),
+          rebase_path(invoker.srcjar_path, root_build_dir),
         ]
       }
 
@@ -2542,6 +2528,7 @@
   #   dex_path: Path to classes.dex file to include (optional).
   #   packaged_resources_path: Path to .ap_ to use.
   #   output_apk_path: Output path for the generated .apk.
+  #   min_sdk_version: The minimum Android SDK version this target supports.
   #   native_lib_placeholders: List of placeholder filenames to add to the apk
   #     (optional).
   #   secondary_native_lib_placeholders: List of placeholder filenames to add to
@@ -2616,10 +2603,18 @@
         invoker.keystore_name,
         "--key-passwd",
         invoker.keystore_password,
+        "--min-sdk-version=${invoker.min_sdk_version}",
       ]
+      if (is_official_build) {
+        args += [ "--best-compression" ]
+      }
       if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) {
         args += [ "--uncompress-dex" ]
       }
+      if (defined(invoker.uncompress_shared_libraries) &&
+          invoker.uncompress_shared_libraries) {
+        args += [ "--uncompress-shared-libraries=True" ]
+      }
       if (defined(invoker.assets_build_config)) {
         inputs += [ invoker.assets_build_config ]
         _rebased_build_config =
@@ -2672,11 +2667,6 @@
       if (_secondary_native_lib_placeholders != []) {
         args += [ "--secondary-native-lib-placeholders=$_secondary_native_lib_placeholders" ]
       }
-
-      if (defined(invoker.uncompress_shared_libraries) &&
-          invoker.uncompress_shared_libraries) {
-        args += [ "--uncompress-shared-libraries=True" ]
-      }
     }
   }
 
@@ -3667,6 +3657,7 @@
       "--secondary-native-lib-placeholders=@FileArg($_rebased_build_config" +
           ":native:secondary_native_library_placeholders)",
       "--android-abi=$android_app_abi",
+      "--min-sdk-version=${invoker.min_sdk_version}",
       "--uncompress-shared-libraries=@FileArg(" +
           "$_rebased_build_config:native:uncompress_shared_libraries)",
     ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index ae31efa..578dd7c3 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -839,11 +839,7 @@
   #     variables = ["color=red"]
   #   }
   template("jinja_template_resources") {
-    # JUnit tests use resource zip files. These must not be put in gen/
-    # directory or they will not be available to tester bots.
-    _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir)
-    _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip"
-
+    _resources_zip = "$target_out_dir/${target_name}.resources.zip"
     _generating_target_name = "${target_name}__template"
 
     action_with_pydeps(_generating_target_name) {
@@ -901,11 +897,6 @@
   #   alternative_android_sdk_dep: Optional. Alternative Android system
   #     android java target to use.
   #   resource_dirs: List of directories containing resources for this target.
-  #   generated_resource_dirs (deprecated):
-  #     **This is deprecated, you only need to specify generated files directly
-  #     in |generated_resource_files|**
-  #   generated_resource_files: List of all resource files for this target
-  #     which are *generated* by a dependency.
   #   android_manifest: AndroidManifest.xml for this target (optional). Will be
   #     merged into apks that directly or indirectly depend on this target.
   #   android_manifest_dep: Target that generates AndroidManifest (if applicable)
@@ -943,18 +934,10 @@
       not_needed(invoker, [ "v14_skip" ])
     }
 
-    # TODO(https://crbug.com/1026378): remove unneeded generated_resource_dirs
-    if (defined(invoker.generated_resource_dirs)) {
-      not_needed(invoker, [ "generated_resource_dirs" ])
-    }
-
     _pass_resource_files = defined(invoker.sources)
     _res_sources_path = "$target_gen_dir/${invoker.target_name}.res.sources"
 
-    # JUnit tests use resource zip files. These must not be put in gen/
-    # directory or they will not be available to tester bots.
-    _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir)
-    _zip_path = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip"
+    _resources_zip = "$target_out_dir/$target_name.resources.zip"
     _r_text_out_path = _base_path + "_R.txt"
     _build_config = _base_path + ".build_config"
     _build_config_target_name = "$target_name$build_config_target_suffix"
@@ -989,16 +972,14 @@
       }
       _resource_files = rebase_path(_sources_build_rel, ".", root_build_dir)
     }
-    if (defined(invoker.generated_resource_files)) {
-      _resource_files += invoker.generated_resource_files
-    }
+
     _rebased_resource_files = rebase_path(_resource_files, root_build_dir)
     write_file(_res_sources_path, _rebased_resource_files)
 
     write_build_config(_build_config_target_name) {
       type = "android_resources"
       build_config = _build_config
-      resources_zip = _zip_path
+      resources_zip = _resources_zip
       res_sources_path = _res_sources_path
 
       if (defined(_srcjar_path)) {
@@ -1039,7 +1020,7 @@
       sources = _resource_files
 
       build_config = _build_config
-      zip_path = _zip_path
+      resources_zip = _resources_zip
       r_text_out_path = _r_text_out_path
 
       if (defined(invoker.r_text_file)) {
@@ -1196,11 +1177,7 @@
   template("java_strings_grd") {
     forward_variables_from(invoker, [ "testonly" ])
 
-    # JUnit tests use resource zip files. These must not be put in gen/
-    # directory or they will not be available to tester bots.
-    _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir)
-    _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip"
-
+    _resources_zip = "$target_out_dir/$target_name.resources.zip"
     _grit_target_name = "${target_name}__grit"
     _grit_output_dir = "$target_gen_dir/${target_name}_grit_output"
 
@@ -1261,11 +1238,7 @@
   template("java_strings_grd_prebuilt") {
     forward_variables_from(invoker, [ "testonly" ])
 
-    # JUnit tests use resource zip files. These must not be put in gen/
-    # directory or they will not be available to tester bots.
-    _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir)
-    _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip"
-
+    _resources_zip = "$target_out_dir/$target_name.resources.zip"
     _zip_target_name = "${target_name}__zip"
 
     zip(_zip_target_name) {
@@ -2993,9 +2966,9 @@
                                [
                                  "disable_checkdiscard",
                                  "disable_r8_outlining",
-                                 "min_sdk_version",
                                  "dexlayout_profile",
                                ])
+        min_sdk_version = _min_sdk_version
         proguard_enabled = _proguard_enabled
         build_config = _build_config
         deps = [
@@ -3256,6 +3229,7 @@
         keystore_name = _keystore_name
         keystore_path = _keystore_path
         keystore_password = _keystore_password
+        min_sdk_version = _min_sdk_version
         uncompress_shared_libraries = _uncompress_shared_libraries
 
         deps = _deps + [ ":$_build_config_target" ]
@@ -4322,15 +4296,9 @@
         if (!_ignore_manifest) {
           android_manifest = "${_output_path}/AndroidManifest.xml"
         }
-        resource_dirs = []
-        generated_resource_dirs = []
-        if (!_strip_resources && _scanned_files.resources != []) {
-          generated_resource_dirs += [ "${_output_path}/res" ]
-        }
-        generated_resource_files = []
+        sources = []
         if (!_strip_resources) {
-          generated_resource_files =
-              rebase_path(_scanned_files.resources, "", _output_path)
+          sources = rebase_path(_scanned_files.resources, "", _output_path)
         }
         if (!_strip_resources && _scanned_files.has_r_text_file) {
           r_text_file = "${_output_path}/R.txt"
@@ -4785,6 +4753,7 @@
         forward_variables_from(invoker,
                                [
                                  "is_multi_abi",
+                                 "min_sdk_version",
                                  "uncompress_dex",
                                ])
         module_name = _module.name
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 55c0e049..92175fd8 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8892254811654238576
\ No newline at end of file
+8892005059433364560
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index a161f67..a9329ac 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8892254806341885184
\ No newline at end of file
+8892005057771346480
\ No newline at end of file
diff --git a/build/util/android_chrome_version.py b/build/util/android_chrome_version.py
index e1ae3bfb..91d31e97 100644
--- a/build/util/android_chrome_version.py
+++ b/build/util/android_chrome_version.py
@@ -90,6 +90,9 @@
         ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32_64'),
         ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'),
         ('WEBVIEW_DEV', 'WEBVIEW_DEV', '32_64'),
+        ('WEBVIEW_32_STABLE', 'WEBVIEW_STABLE', '32'),
+        ('WEBVIEW_32_BETA', 'WEBVIEW_BETA', '32'),
+        ('WEBVIEW_32_DEV', 'WEBVIEW_DEV', '32'),
     ]
 }
 
diff --git a/build/util/version.gni b/build/util/version.gni
index a4fff4d3..77bd9dd8 100644
--- a/build/util/version.gni
+++ b/build/util/version.gni
@@ -48,15 +48,7 @@
       "webview_dev_version_code = \"@WEBVIEW_DEV_VERSION_CODE@\" "
 
   if (target_cpu == "arm64" || target_cpu == "x64") {
-    _version_dictionary_template +=
-        "monochrome_32_version_code = \"@MONOCHROME_32_VERSION_CODE@\" " +
-        "monochrome_32_64_version_code = \"@MONOCHROME_32_64_VERSION_CODE@\" " +
-        "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" " +
-        "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " +
-        "trichrome_32_version_code = \"@TRICHROME_32_VERSION_CODE@\" " +
-        "trichrome_32_64_version_code = \"@TRICHROME_32_64_VERSION_CODE@\" " +
-        "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" " +
-        "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" "
+    _version_dictionary_template += "monochrome_32_version_code = \"@MONOCHROME_32_VERSION_CODE@\" " + "monochrome_32_64_version_code = \"@MONOCHROME_32_64_VERSION_CODE@\" " + "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" " + "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " + "trichrome_32_version_code = \"@TRICHROME_32_VERSION_CODE@\" " + "trichrome_32_64_version_code = \"@TRICHROME_32_64_VERSION_CODE@\" " + "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" " + "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" " + "webview_32_stable_version_code = \"@WEBVIEW_32_STABLE_VERSION_CODE@\" " + "webview_32_beta_version_code = \"@WEBVIEW_32_BETA_VERSION_CODE@\" " + "webview_32_dev_version_code = \"@WEBVIEW_32_DEV_VERSION_CODE@\" "
   }
 
   _script_arguments += [
@@ -119,6 +111,9 @@
                            "webview_beta_version_code",
                            "webview_dev_version_code",
                            "webview_stable_version_code",
+                           "webview_32_beta_version_code",
+                           "webview_32_dev_version_code",
+                           "webview_32_stable_version_code",
                          ])
 
   chrome_version_name = chrome_version_full
@@ -144,6 +139,9 @@
       "TrichromeChrome3264: $trichrome_32_64_version_code",
       "TrichromeChrome6432: $trichrome_64_32_version_code",
       "TrichromeChrome64: $trichrome_64_version_code",
+      "AndroidWebview32Stable: $webview_32_stable_version_code",
+      "AndroidWebview32Beta: $webview_32_beta_version_code",
+      "AndroidWebview32Dev: $webview_32_dev_version_code",
     ]
   }
 
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index d13ed64..47477510 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -128,12 +128,10 @@
   // for them.
   DCHECK(picture_layer_inputs_.client);
 
-  picture_layer_inputs_.recorded_viewport =
-      picture_layer_inputs_.client->PaintableRegion();
+  auto recorded_viewport = picture_layer_inputs_.client->PaintableRegion();
 
   updated |= recording_source_->UpdateAndExpandInvalidation(
-      &last_updated_invalidation_, layer_size,
-      picture_layer_inputs_.recorded_viewport);
+      &last_updated_invalidation_, layer_size, recorded_viewport);
 
   if (updated) {
     picture_layer_inputs_.display_list =
@@ -269,7 +267,6 @@
     // for example), even though it has resized making the recording source no
     // longer valid. In this case just destroy the recording source.
     recording_source_->SetEmptyBounds();
-    picture_layer_inputs_.recorded_viewport = gfx::Rect();
     picture_layer_inputs_.display_list = nullptr;
     picture_layer_inputs_.painter_reported_memory_usage = 0;
   }
diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h
index 05e41d7..9fe8d0d 100644
--- a/cc/layers/picture_layer.h
+++ b/cc/layers/picture_layer.h
@@ -71,7 +71,6 @@
     bool nearest_neighbor = false;
     bool transformed_rasterization_allowed = false;
     bool is_backdrop_filter_mask = false;
-    gfx::Rect recorded_viewport;
     scoped_refptr<DisplayItemList> display_list;
     size_t painter_reported_memory_usage = 0;
   };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index a45f4db..7c2a68b 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -3850,12 +3850,8 @@
 
   browser_controls_offset_manager_->ScrollBegin();
 
-  // TODO(majidvp): get rid of touch_scrolling_ and set is_direct_manipulation
-  // in input_handler_proxy instead.
-  touch_scrolling_ = type == InputHandler::TOUCHSCREEN;
   wheel_scrolling_ = type == InputHandler::WHEEL;
   middle_click_autoscrolling_ = type == InputHandler::AUTOSCROLL;
-  scroll_state->set_is_direct_manipulation(touch_scrolling_);
 
   LatchToScroller(scroll_state, scrolling_node);
 
@@ -4642,8 +4638,6 @@
   float initial_top_controls_offset =
       browser_controls_offset_manager_->ControlsTopOffset();
 
-  scroll_state->set_is_direct_manipulation(touch_scrolling_);
-
   ScrollLatchedScroller(scroll_state);
 
   bool did_scroll_x = scroll_state->caused_scroll_x();
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 4f3f63c..947a3cce 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -1062,7 +1062,6 @@
   std::unique_ptr<LayerTreeImpl> recycle_tree_;
 
   InputHandlerClient* input_handler_client_ = nullptr;
-  bool touch_scrolling_ = false;
   bool wheel_scrolling_ = false;
   bool middle_click_autoscrolling_ = false;
   bool scroll_affects_scroll_handler_ = false;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 042cc5c..4e8d395d 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -489,7 +489,9 @@
     // The point hits squash1 layer and also scroll layer, because scroll layer
     // is not an ancestor of squash1 layer, we cannot scroll on impl thread.
     InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(230, 150), gfx::Vector2dF(0, 10)).get(),
+        BeginState(gfx::Point(230, 150), gfx::Vector2dF(0, 10),
+                   InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
     ASSERT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
     ASSERT_EQ(MainThreadScrollingReason::kFailedHitTest,
@@ -497,7 +499,9 @@
 
     // The point hits squash1 layer and also scrollbar layer.
     status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(350, 150), gfx::Vector2dF(0, 10)).get(),
+        BeginState(gfx::Point(350, 150), gfx::Vector2dF(0, 10),
+                   InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
     ASSERT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
     ASSERT_EQ(MainThreadScrollingReason::kFailedHitTest,
@@ -506,7 +510,9 @@
     // The point hits squash2 layer and also scroll layer, because scroll layer
     // is an ancestor of squash2 layer, we should scroll on impl.
     status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(230, 450), gfx::Vector2dF(0, 10)).get(),
+        BeginState(gfx::Point(230, 450), gfx::Vector2dF(0, 10),
+                   InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
     ASSERT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   }
@@ -572,25 +578,31 @@
   }
 
   std::unique_ptr<ScrollState> BeginState(const gfx::Point& point,
-                                          const gfx::Vector2dF& delta_hint) {
+                                          const gfx::Vector2dF& delta_hint,
+                                          InputHandler::ScrollInputType type) {
     ScrollStateData scroll_state_data;
     scroll_state_data.is_beginning = true;
     scroll_state_data.position_x = point.x();
     scroll_state_data.position_y = point.y();
     scroll_state_data.delta_x_hint = delta_hint.x();
     scroll_state_data.delta_y_hint = delta_hint.y();
+    scroll_state_data.is_direct_manipulation =
+        type == InputHandler::TOUCHSCREEN;
     std::unique_ptr<ScrollState> scroll_state(
         new ScrollState(scroll_state_data));
     return scroll_state;
   }
 
   std::unique_ptr<ScrollState> UpdateState(const gfx::Point& point,
-                                           const gfx::Vector2dF& delta) {
+                                           const gfx::Vector2dF& delta,
+                                           InputHandler::ScrollInputType type) {
     ScrollStateData scroll_state_data;
     scroll_state_data.delta_x = delta.x();
     scroll_state_data.delta_y = delta.y();
     scroll_state_data.position_x = point.x();
     scroll_state_data.position_y = point.y();
+    scroll_state_data.is_direct_manipulation =
+        type == InputHandler::TOUCHSCREEN;
     std::unique_ptr<ScrollState> scroll_state(
         new ScrollState(scroll_state_data));
     return scroll_state;
@@ -1049,14 +1061,14 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollBeforeRootLayerAttached) {
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 1)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 1), InputHandler::WHEEL).get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
             status.main_thread_scrolling_reasons);
 
   status = host_impl_->RootScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 1)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 1), InputHandler::WHEEL).get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
@@ -1068,14 +1080,17 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
 
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get());
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10)));
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
@@ -1088,14 +1103,17 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
 
   EXPECT_TRUE(host_impl_->IsActivelyScrolling());
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(host_impl_->IsActivelyScrolling());
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->IsActivelyScrolling());
@@ -1104,7 +1122,8 @@
 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
   // We should not crash when trying to scroll an empty layer tree.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
@@ -1126,7 +1145,8 @@
   // We should not crash when trying to scroll after the renderer initialization
   // fails.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
@@ -1143,7 +1163,8 @@
       InputHandler::SCROLL_ON_IMPL_THREAD,
       host_impl_
           ->ScrollBegin(BeginState(gfx::Point(),
-                                   gfx::ScrollOffsetToVector2dF(scroll_delta))
+                                   gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                   InputHandler::WHEEL)
                             .get(),
                         InputHandler::WHEEL)
           .thread);
@@ -1154,9 +1175,10 @@
 
   // We should still be scrolling, because the scrolled layer also exists in the
   // new tree.
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta))
-          .get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(),
+                                   gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                   InputHandler::WHEEL)
+                           .get());
   host_impl_->ScrollEnd();
   std::unique_ptr<ScrollAndScaleSet> scroll_info =
       host_impl_->ProcessScrollDeltas();
@@ -1168,12 +1190,15 @@
   SetupViewportLayersOuterScrolls(gfx::Size(100, 100), gfx::Size(1000, 1000));
 
   auto status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(30, 30), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(30, 30), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(host_impl_->active_tree()->CurrentlyScrollingNode());
   EXPECT_TRUE(host_impl_->IsActivelyScrolling());
 
@@ -1211,7 +1236,7 @@
 
   // But they don't influence the actual handling of the scroll gestures.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL).get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
@@ -1245,7 +1270,8 @@
 
   // But they don't influence the actual handling of the scroll gestures.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
@@ -1276,14 +1302,15 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL).get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
             status.main_thread_scrolling_reasons);
 
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
@@ -1328,7 +1355,9 @@
   // The point hits squash layer and also scrollbar layer, but because the
   // scrollbar layer is a drawn scrollbar, we cannot scroll on the impl thread.
   auto status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(350, 150), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(350, 150), gfx::Vector2d(0, 10),
+                 InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
@@ -1337,7 +1366,9 @@
   // The point hits the drawn scrollbar layer completely and should scroll on
   // the impl thread.
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(350, 500), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(350, 500), gfx::Vector2d(0, 10),
+                 InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
@@ -1354,7 +1385,8 @@
 
   // All scroll types inside the non-fast scrollable region should fail.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
@@ -1362,7 +1394,9 @@
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25)));
 
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
@@ -1371,26 +1405,33 @@
 
   // All scroll types outside this region should succeed.
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
 
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25)));
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
 
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10)).get(),
+      BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get());
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
 }
@@ -1408,19 +1449,23 @@
   // This point would fall into the non-fast scrollable region except that we've
   // moved the layer left by 25 pixels.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(40, 10), gfx::Vector2d(0, 1)).get(),
+      BeginState(gfx::Point(40, 10), gfx::Vector2d(0, 1), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
 
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10)));
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 1)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 1), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   // This point is still inside the non-fast region.
   status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 1)).get(),
+      BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 1), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
@@ -1433,8 +1478,10 @@
   DrawFrame();
 
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1446,8 +1493,10 @@
   DrawFrame();
 
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1458,72 +1507,87 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(-10, 0)).get(),
+      BeginState(gfx::Point(), gfx::Vector2d(-10, 0), InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
 
   // Trying to scroll to the left/top will not succeed.
-  EXPECT_FALSE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
-          .did_scroll);
-  EXPECT_FALSE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
-          .did_scroll);
-  EXPECT_FALSE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
-          .did_scroll);
+  EXPECT_FALSE(host_impl_
+                   ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
+                                          InputHandler::TOUCHSCREEN)
+                                  .get())
+                   .did_scroll);
+  EXPECT_FALSE(host_impl_
+                   ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
+                                          InputHandler::TOUCHSCREEN)
+                                  .get())
+                   .did_scroll);
+  EXPECT_FALSE(host_impl_
+                   ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10),
+                                          InputHandler::TOUCHSCREEN)
+                                  .get())
+                   .did_scroll);
 
   // Scrolling to the right/bottom will succeed.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 0)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 10)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 0),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
 
   // Scrolling to left/top will now succeed.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
 
   // Scrolling diagonally against an edge will succeed.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, -10)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
-          .did_scroll);
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 10)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, -10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
 
   // Trying to scroll more than the available space will also succeed.
   EXPECT_TRUE(
       host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(5000, 5000)).get())
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(5000, 5000),
+                                 InputHandler::TOUCHSCREEN)
+                         .get())
           .did_scroll);
 }
 
@@ -1534,16 +1598,19 @@
 
   gfx::Point pointer_position(10, 10);
   gfx::Vector2dF x_delta(20, 0);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
@@ -1575,16 +1642,19 @@
 
   gfx::Point pointer_position(10, 10);
   gfx::Vector2dF y_delta(0, 20);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, y_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, y_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, y_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, y_delta, InputHandler::WHEEL).get());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
@@ -1616,16 +1686,19 @@
 
   gfx::Point pointer_position(10, 10);
   gfx::Vector2dF delta(20, 20);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, delta, InputHandler::WHEEL).get());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
 
@@ -1660,7 +1733,9 @@
 
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_->ScrollAnimatedBegin(BeginState(pointer_position, delta).get())
+      host_impl_
+          ->ScrollAnimatedBegin(
+              BeginState(pointer_position, delta, InputHandler::WHEEL).get())
           .thread);
   host_impl_->ScrollAnimated(pointer_position, delta);
   host_impl_->ScrollEnd();
@@ -1712,14 +1787,17 @@
 
   gfx::Point pointer_position(10, 10);
   gfx::Vector2dF x_delta(20, 0);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
 
   viz::BeginFrameArgs begin_frame_args =
@@ -1742,11 +1820,13 @@
   EXPECT_EQ(0, current_offset.y());
 
   // Interrupt the snap animation with ScrollBegin.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
   EXPECT_EQ(TargetSnapAreaElementIds(),
             GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
@@ -1769,15 +1849,18 @@
 
   gfx::Point pointer_position(10, 10);
   gfx::Vector2dF x_delta(50, 0);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // There is a snap target at 50, scroll to it directly.
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
 
   viz::BeginFrameArgs begin_frame_args =
@@ -1815,16 +1898,18 @@
   // Should be (10, 10) in the scroller's coordinate.
   gfx::Point pointer_position(2, 2);
   gfx::Vector2dF delta(4, 4);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // Should be (20, 20) in the scroller's coordinate.
-  InputHandlerScrollResult result =
-      host_impl_->ScrollBy(UpdateState(pointer_position, delta).get());
+  InputHandlerScrollResult result = host_impl_->ScrollBy(
+      UpdateState(pointer_position, delta, InputHandler::WHEEL).get());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), overflow->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset);
 
@@ -1852,16 +1937,18 @@
   // Should be (10, 10) in the scroller's coordinate.
   gfx::Point pointer_position(2, 2);
   gfx::Vector2dF delta(4, 4);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // Should be (20, 20) in the scroller's coordinate.
-  InputHandlerScrollResult result =
-      host_impl_->ScrollBy(UpdateState(pointer_position, delta).get());
+  InputHandlerScrollResult result = host_impl_->ScrollBy(
+      UpdateState(pointer_position, delta, InputHandler::WHEEL).get());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), overflow->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset);
 
@@ -1901,15 +1988,18 @@
   gfx::Vector2dF diagonal_delta(-10, -10);
 
   // OverscrollBehaviorTypeAuto shouldn't prevent scroll propagation.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(30, 30), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
@@ -1922,46 +2012,54 @@
 
   // OverscrollBehaviorContain on x should prevent propagations of scroll
   // on x.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // OverscrollBehaviorContain on x shouldn't prevent propagations of
   // scroll on y.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, y_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, y_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, y_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, y_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // A scroll update with both x & y delta will adhere to the most restrictive
   // case.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(pointer_position, diagonal_delta).get(),
-                        InputHandler::WHEEL)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(pointer_position, diagonal_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, diagonal_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, diagonal_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
@@ -1975,46 +2073,54 @@
 
   // OverscrollBehaviorContain on y shouldn't prevent propagations of
   // scroll on x.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // OverscrollBehaviorContain on y should prevent propagations of scroll
   // on y.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, y_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, y_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, y_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, y_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
   // A scroll update with both x & y delta will adhere to the most restrictive
   // case.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(pointer_position, diagonal_delta).get(),
-                        InputHandler::WHEEL)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(pointer_position, diagonal_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, diagonal_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, diagonal_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
@@ -2027,18 +2133,24 @@
 
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(BeginState(pointer_position, x_delta).get(),
-                              InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(
+              BeginState(pointer_position, x_delta, InputHandler::WHEEL).get(),
+              InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(pointer_position, x_delta).get());
-  host_impl_->ScrollBy(UpdateState(pointer_position, -x_delta).get());
-  host_impl_->ScrollBy(UpdateState(pointer_position, y_delta).get());
-  host_impl_->ScrollBy(UpdateState(pointer_position, -y_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, x_delta, InputHandler::WHEEL).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, -x_delta, InputHandler::WHEEL).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, y_delta, InputHandler::WHEEL).get());
+  host_impl_->ScrollBy(
+      UpdateState(pointer_position, -y_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
@@ -2061,13 +2173,16 @@
 
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(scroll_position, scroll_delta).get(),
+                ->ScrollBegin(BeginState(scroll_position, scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(scroll_position, scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(scroll_position, scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
@@ -2078,13 +2193,16 @@
 
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(scroll_position, scroll_delta).get(),
+                ->ScrollBegin(BeginState(scroll_position, scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(scroll_position, scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(scroll_position, scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
@@ -2094,13 +2212,16 @@
 
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(scroll_position, scroll_delta).get(),
+                ->ScrollBegin(BeginState(scroll_position, scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
 
-  host_impl_->ScrollBy(UpdateState(scroll_position, scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(scroll_position, scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
@@ -2115,7 +2236,8 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(25, 25), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(25, 25), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
@@ -2372,9 +2494,10 @@
     // TODO(bokan): What are the delta_hints for a GSB that's sent for a pinch
     // gesture that doesn't cause (initial) scrolling?
     // https://crbug.com/1030262
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(50, 50), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -2401,21 +2524,25 @@
     SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
 
     float page_scale_delta = 2;
-    host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+            .get(),
+        InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
     host_impl_->PinchGestureEnd(gfx::Point(), true);
     host_impl_->ScrollEnd();
 
     gfx::Vector2d scroll_delta(0, 10);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::WHEEL)
-            .thread);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::WHEEL)
+                                    .get(),
+                                InputHandler::WHEEL)
+                  .thread);
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     host_impl_->ScrollEnd();
 
     std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -2501,9 +2628,10 @@
   EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500),
                    outer_scroll_layer->MaxScrollOffset());
 
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(250, 250), gfx::Vector2dF()).get(),
-      InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, gfx::Point(0, 0));
   host_impl_->PinchGestureEnd(gfx::Point(0, 0), true);
@@ -2516,11 +2644,13 @@
                    inner_scroll_layer->CurrentScrollOffset());
 
   // Scroll down - only the inner viewport should scroll.
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
-      InputHandler::TOUCHSCREEN);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+  host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   host_impl_->ScrollEnd();
 
   EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
@@ -2531,10 +2661,13 @@
   // Scroll down - outer viewport should start scrolling after the inner is at
   // its maximum.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get(),
+      BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   host_impl_->ScrollEnd();
 
   EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250),
@@ -2566,10 +2699,14 @@
 
   // Scroll only the layout viewport.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.125f, 0.125f)).get(),
+      BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.125f, 0.125f),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(250, 250), gfx::Vector2dF(0.125f, 0.125f)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(250, 250),
+                                   gfx::Vector2dF(0.125f, 0.125f),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
                       outer_scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0),
@@ -2580,10 +2717,14 @@
 
   // Now that we zoomed in, the scroll should be applied to the inner viewport.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.5f, 0.5f)).get(),
+      BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.5f, 0.5f),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(250, 250), gfx::Vector2dF(0.5f, 0.5f)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(250, 250),
+                                   gfx::Vector2dF(0.5f, 0.5f),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
                       outer_scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.25f, 0.25f),
@@ -2612,9 +2753,10 @@
   EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500),
                    outer_scroll_layer->MaxScrollOffset());
 
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(250, 250), gfx::Vector2dF()).get(),
-      InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
 
   host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
@@ -2626,8 +2768,9 @@
   // Needed so that the pinch is accounted for in draw properties.
   DrawFrame();
 
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(250, 250), gfx::Vector2dF(10, 10)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(250, 250), gfx::Vector2dF(10, 10),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
                    outer_scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(130, 130),
@@ -2635,8 +2778,10 @@
 
   DrawFrame();
 
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(250, 250), gfx::Vector2dF(400, 400)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(250, 250),
+                                   gfx::Vector2dF(400, 400),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(80, 80),
                    outer_scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250),
@@ -2664,8 +2809,9 @@
 
   // Pinch in within the margins. The scroll should stay exactly locked to the
   // bottom and right.
-  host_impl_->ScrollBegin(BeginState(anchor, gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(anchor, gfx::Vector2dF(), InputHandler::TOUCHSCREEN).get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, anchor);
   host_impl_->PinchGestureEnd(anchor, true);
@@ -2682,8 +2828,9 @@
   // Pinch in within the margins. The scroll should stay exactly locked to the
   // top and left.
   anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
-  host_impl_->ScrollBegin(BeginState(anchor, gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(anchor, gfx::Vector2dF(), InputHandler::TOUCHSCREEN).get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, anchor);
   host_impl_->PinchGestureEnd(anchor, true);
@@ -2700,8 +2847,9 @@
   // Pinch in just outside the margin. There should be no snapping.
   offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
   anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
-  host_impl_->ScrollBegin(BeginState(anchor, gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(anchor, gfx::Vector2dF(), InputHandler::TOUCHSCREEN).get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, anchor);
   host_impl_->PinchGestureEnd(anchor, true);
@@ -2719,8 +2867,9 @@
   offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
   anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
                       viewport_size.height() - offsetFromEdge);
-  host_impl_->ScrollBegin(BeginState(anchor, gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(anchor, gfx::Vector2dF(), InputHandler::TOUCHSCREEN).get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, anchor);
   host_impl_->PinchGestureEnd(anchor, true);
@@ -2748,10 +2897,12 @@
   // Scroll by a small amount, there should be no bubbling to the outer
   // viewport.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(0, 0), gfx::Vector2dF(10, 20)).get(),
+      BeginState(gfx::Point(0, 0), gfx::Vector2dF(10, 20), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(10, 20)).get());
+      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(10, 20), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10),
@@ -2760,11 +2911,13 @@
 
   // Scroll by the inner viewport's max scroll extent, the remainder
   // should bubble up to the outer viewport.
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
-      InputHandler::WHEEL);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+  host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::WHEEL)
+                              .get(),
+                          InputHandler::WHEEL);
+  host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                   InputHandler::WHEEL)
+                           .get());
   host_impl_->ScrollEnd();
 
   EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
@@ -2774,11 +2927,13 @@
 
   // Scroll by the outer viewport's max scroll extent, it should all go to the
   // outer viewport.
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(0, 0), gfx::Vector2dF(190, 180)).get(),
-      InputHandler::WHEEL);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(190, 180)).get());
+  host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(190, 180),
+                                     InputHandler::WHEEL)
+                              .get(),
+                          InputHandler::WHEEL);
+  host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(190, 180),
+                                   InputHandler::WHEEL)
+                           .get());
   host_impl_->ScrollEnd();
 
   EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100),
@@ -2795,13 +2950,16 @@
       new LatencyInfoSwapPromise(latency_info));
 
   SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::TOUCHSCREEN)
+          .get());
   host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(
       std::move(swap_promise));
   host_impl_->ScrollEnd();
@@ -2836,13 +2994,17 @@
   DrawFrame();
 
   {
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(21, 21), gfx::Vector2d(5, 5)).get(),
-        InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(5, 5)).get());
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(100, 100)).get());
+    host_impl_->ScrollBegin(BeginState(gfx::Point(21, 21), gfx::Vector2d(5, 5),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21), gfx::Vector2d(5, 5),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21),
+                                     gfx::Vector2d(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     // The child should be fully scrolled by the first ScrollBy.
@@ -2860,17 +3022,22 @@
   }
 
   {
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(21, 21), gfx::Vector2d(3, 4)).get(),
-        InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(3, 4)).get());
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1)).get());
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1)).get());
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1)).get());
+    host_impl_->ScrollBegin(BeginState(gfx::Point(21, 21), gfx::Vector2d(3, 4),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21), gfx::Vector2d(3, 4),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(21, 21), gfx::Vector2d(2, 1),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     // The ScrollBy's should scroll the parent to its extent.
@@ -2902,9 +3069,10 @@
     SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
 
     float page_scale_delta = 2;
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(50, 50), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -2925,9 +3093,10 @@
     SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
     float page_scale_delta = 10;
 
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(50, 50), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -2952,8 +3121,10 @@
             scroll_layer->element_id(), gfx::ScrollOffset(50, 50));
 
     float page_scale_delta = 0.1f;
-    host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+            .get(),
+        InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
     host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -2980,9 +3151,10 @@
             scroll_layer->element_id(), gfx::ScrollOffset(20, 20));
 
     float page_scale_delta = 1;
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(10, 10), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
@@ -3010,12 +3182,16 @@
 
     float page_scale_delta = 1;
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(10, 10), gfx::Vector2dF(-10, -10)).get(),
+        BeginState(gfx::Point(10, 10), gfx::Vector2dF(-10, -10),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(10, 10), gfx::Vector2d(-10, -10)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(10, 10),
+                                     gfx::Vector2d(-10, -10),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
     host_impl_->PinchGestureEnd(gfx::Point(20, 20), true);
     host_impl_->ScrollEnd();
@@ -3039,9 +3215,10 @@
         ->scroll_tree.UpdateScrollOffsetBaseForTesting(
             scroll_layer->element_id(), gfx::ScrollOffset(0, 0));
 
-    host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(2, gfx::Point(0, 0));
     host_impl_->PinchGestureUpdate(1, gfx::Point(0, 0));
@@ -3049,8 +3226,9 @@
     // Needed so layer transform includes page scale.
     DrawFrame();
 
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2d(10, 10)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2d(10, 10),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->PinchGestureUpdate(1, gfx::Point(10, 10));
     host_impl_->PinchGestureEnd(gfx::Point(10, 10), true);
     host_impl_->ScrollEnd();
@@ -3085,13 +3263,16 @@
                                                      gfx::ScrollOffset(0, 20));
 
   float page_scale_delta = 1;
-  host_impl_->ScrollBegin(
-      BeginState(gfx::Point(10, 10), gfx::Vector2dF()).get(),
-      InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(),
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(10, 10), gfx::Vector2dF(0, -1.001f)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(10, 10),
+                                   gfx::Vector2dF(0, -1.001f),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 9));
   host_impl_->PinchGestureEnd(gfx::Point(10, 9), true);
   host_impl_->ScrollEnd();
@@ -3127,10 +3308,12 @@
           scroll_layer->element_id(), gfx::ScrollOffset(0, 20.5f));
 
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(10, 10), gfx::Vector2dF(0, -1)).get(),
+      BeginState(gfx::Point(10, 10), gfx::Vector2dF(0, -1), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(10, 10), gfx::Vector2dF(0, -1)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(10, 10), gfx::Vector2dF(0, -1),
+                                   InputHandler::WHEEL)
+                           .get());
   host_impl_->ScrollEnd();
 
   gfx::ScrollOffset active_base =
@@ -3751,8 +3934,9 @@
     }
 
     // If no scroll happened during a scroll gesture, it should have no effect.
-    host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                            InputHandler::WHEEL);
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::WHEEL).get(),
+        InputHandler::WHEEL);
     host_impl_->ScrollEnd();
     EXPECT_FALSE(did_request_next_frame_);
     EXPECT_FALSE(did_request_redraw_);
@@ -3761,9 +3945,12 @@
 
     // For Aura Overlay Scrollbar, if no scroll happened during a scroll
     // gesture, shows scrollbars and schedules a delay fade out.
-    host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                            InputHandler::WHEEL);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 0)).get());
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::WHEEL).get(),
+        InputHandler::WHEEL);
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), gfx::Vector2dF(0, 0), InputHandler::WHEEL)
+            .get());
     host_impl_->ScrollEnd();
     EXPECT_FALSE(did_request_next_frame_);
     EXPECT_FALSE(did_request_redraw_);
@@ -3794,9 +3981,12 @@
     // After a scroll, a scrollbar animation should be scheduled about 20ms from
     // now.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(), gfx::Vector2dF(0, 5)).get(),
+        BeginState(gfx::Point(), gfx::Vector2dF(0, 5), InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 5)).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), gfx::Vector2dF(0, 5), InputHandler::WHEEL)
+            .get());
     EXPECT_FALSE(did_request_next_frame_);
     EXPECT_TRUE(did_request_redraw_);
     did_request_redraw_ = false;
@@ -3943,9 +4133,12 @@
                              scroll->element_id()));
     }
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(), gfx::Vector2dF(0, 5)).get(),
+        BeginState(gfx::Point(), gfx::Vector2dF(0, 5), InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 5)).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), gfx::Vector2dF(0, 5), InputHandler::WHEEL)
+            .get());
     host_impl_->ScrollEnd();
 
     CreatePendingTree();
@@ -4069,10 +4262,12 @@
 
   // Scroll on root should flash all scrollbars.
   host_impl_->RootScrollBegin(
-      BeginState(gfx::Point(20, 20), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(20, 20), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   host_impl_->ScrollBy(
-      UpdateState(gfx::Point(20, 20), gfx::Vector2d(0, 10)).get());
+      UpdateState(gfx::Point(20, 20), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   EXPECT_TRUE(scrollbar_1_->Opacity());
@@ -4082,8 +4277,10 @@
   ResetScrollbars();
 
   // Scroll on child should flash all scrollbars.
-  host_impl_->ScrollAnimatedBegin(
-      BeginState(gfx::Point(70, 70), gfx::Vector2dF(0, 100)).get());
+  host_impl_->ScrollAnimatedBegin(BeginState(gfx::Point(70, 70),
+                                             gfx::Vector2dF(0, 100),
+                                             InputHandler::WHEEL)
+                                      .get());
   host_impl_->ScrollAnimated(gfx::Point(70, 70), gfx::Vector2d(0, 100));
   host_impl_->ScrollEnd();
 
@@ -4162,7 +4359,8 @@
   // Wheel scroll on root scrollbar should process on impl thread.
   {
     InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(1, 1), gfx::Vector2dF()).get(),
+        BeginState(gfx::Point(1, 1), gfx::Vector2dF(), InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
     host_impl_->ScrollEnd();
@@ -4170,9 +4368,11 @@
 
   // Touch scroll on root scrollbar should process on main thread.
   {
-    InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(1, 1), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    InputHandler::ScrollStatus status =
+        host_impl_->ScrollBegin(BeginState(gfx::Point(1, 1), gfx::Vector2dF(),
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN);
     EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
     EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling,
               status.main_thread_scrolling_reasons);
@@ -4181,7 +4381,8 @@
   // Wheel scroll on scrollbar should process on impl thread.
   {
     InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(51, 51), gfx::Vector2dF()).get(),
+        BeginState(gfx::Point(51, 51), gfx::Vector2dF(), InputHandler::WHEEL)
+            .get(),
         InputHandler::WHEEL);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
     EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
@@ -4191,9 +4392,11 @@
 
   // Touch scroll on scrollbar should process on main thread.
   {
-    InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-        BeginState(gfx::Point(51, 51), gfx::Vector2dF()).get(),
-        InputHandler::TOUCHSCREEN);
+    InputHandler::ScrollStatus status =
+        host_impl_->ScrollBegin(BeginState(gfx::Point(51, 51), gfx::Vector2dF(),
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN);
     EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
     EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling,
               status.main_thread_scrolling_reasons);
@@ -4339,9 +4542,12 @@
   // Scrolling the viewport should result in a scrollbar animation update.
   animation_task_.Reset();
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(10, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(10, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 10)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(10, 10), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
   EXPECT_FALSE(animation_task_.is_null());
   animation_task_.Reset();
@@ -4423,9 +4629,12 @@
 
   // Scroll the page down which moves the thumb down.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 100)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 100), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 100)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 100), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   // Move the mouse near the thumb in the top position.
@@ -4434,9 +4643,12 @@
 
   // Scroll the page up which moves the thumb back up.
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, -100)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, -100), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -100)).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -100), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   // Move the mouse near the thumb in the top position.
@@ -4650,13 +4862,16 @@
   }
 
   // Scrolling should update metadata immediately.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::WHEEL)
-          .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   {
     viz::CompositorFrameMetadata metadata =
         host_impl_->MakeCompositorFrameMetadata();
@@ -4670,8 +4885,10 @@
   }
 
   // Page scale should update metadata correctly (shrinking only the viewport).
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, gfx::Point());
   host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -5199,7 +5416,8 @@
 
   // Scroll event is ignored because layer is not scrollable.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
@@ -5329,12 +5547,13 @@
   EXPECT_VIEWPORT_GEOMETRIES(1);
   EXPECT_EQ(gfx::SizeF(50, 50), active_tree->ScrollableSize());
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 
   host_impl_->browser_controls_manager()->ScrollBegin();
 
@@ -5385,19 +5604,21 @@
   EXPECT_VIEWPORT_GEOMETRIES(1.0f);
   EXPECT_EQ(gfx::SizeF(200, 1000), active_tree->ScrollableSize());
 
-  ASSERT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  ASSERT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 
   // Hide the browser controls by 25px. The outer clip should expand by 50px as
   // because the outer viewport is sized based on the minimum scale, in this
   // case 0.5. Therefore, changes to the outer viewport need to be divided by
   // the minimum scale as well.
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, 0), gfx::Vector2dF(0, 25)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(0, 25),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_VIEWPORT_GEOMETRIES(0.5f);
 
   host_impl_->ScrollEnd();
@@ -5433,12 +5654,13 @@
   EXPECT_EQ(gfx::Size(50, 15), scrollbar_layer->bounds());
   EXPECT_EQ(gfx::Rect(20, 0, 10, 3), scrollbar_layer->ComputeThumbQuadRect());
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 
   host_impl_->browser_controls_manager()->ScrollBegin();
 
@@ -5486,12 +5708,14 @@
   DrawFrame();
 
   gfx::Vector2dF top_controls_scroll_delta(0, 5.25f);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), top_controls_scroll_delta).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), top_controls_scroll_delta,
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
 
   // Make the test scroll delta a fractional amount, to verify that the
   // fixed container size delta is (1) non-zero, and (2) fractional, and
@@ -5525,13 +5749,16 @@
   outer_scroll->SetDrawsContent(true);
   host_impl_->active_tree()->PushPageScaleFromMainThread(2, 1, 2);
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 50)).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 50),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
 
   // The entire scroll delta should have been used to hide the browser controls.
   // The viewport layers should be resized back to their full sizes.
@@ -5541,23 +5768,28 @@
   EXPECT_EQ(100, outer_scroll->bounds().height());
 
   // The inner viewport should be scrollable by 50px * page_scale.
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 100)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 100),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_EQ(50, inner_scroll->CurrentScrollOffset().y());
   EXPECT_EQ(0, outer_scroll->CurrentScrollOffset().y());
   EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
 
   host_impl_->ScrollEnd();
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -50)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -50),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
   EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
             outer_scroll->scroll_tree_index());
 
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -50)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -50),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
 
   // The entire scroll delta should have been used to show the browser controls.
   // The outer viewport should be resized to accomodate and scrolled to the
@@ -5570,16 +5802,21 @@
 
   // Now when we continue scrolling, make sure the outer viewport gets scrolled
   // since it wasn't scrollable when the scroll began.
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -20)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -20),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_EQ(25, outer_scroll->CurrentScrollOffset().y());
   EXPECT_EQ(15, inner_scroll->CurrentScrollOffset().y());
 
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -30)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, -30),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   EXPECT_EQ(25, outer_scroll->CurrentScrollOffset().y());
   EXPECT_EQ(0, inner_scroll->CurrentScrollOffset().y());
 
-  host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2dF(0.f, -50)).get());
+  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0.f, -50),
+                                   InputHandler::TOUCHSCREEN)
+                           .get());
   host_impl_->ScrollEnd();
 
   EXPECT_EQ(0, outer_scroll->CurrentScrollOffset().y());
@@ -5600,12 +5837,14 @@
   host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1, 2);
 
   gfx::Vector2dF top_controls_scroll_delta(0, 20);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), top_controls_scroll_delta).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), top_controls_scroll_delta,
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
 
   // Scroll down, the browser controls hiding should expand the viewport size so
   // the delta should be equal to the scroll distance.
@@ -5699,10 +5938,13 @@
   gfx::Vector2dF scroll_delta(0, 25);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   host_impl_->ScrollEnd();
 
   // Browser controls should be hidden
@@ -5896,10 +6138,13 @@
   gfx::Vector2dF scroll_delta(0, 25);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
 
   // scrolling down at the max extents no longer hides the browser controls
   EXPECT_EQ(1, host_impl_->active_tree()->CurrentTopControlsShownRatio());
@@ -5926,10 +6171,13 @@
   scroll_delta = gfx::Vector2dF(0, -25);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   host_impl_->ScrollEnd();
 
   // The viewport offset shouldn't have changed.
@@ -5956,10 +6204,13 @@
   gfx::Vector2dF scroll_delta(0, 25);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   host_impl_->ScrollEnd();
 
   EXPECT_FLOAT_EQ(
@@ -5994,10 +6245,13 @@
   gfx::Vector2dF scroll_delta(0, 15);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
 
   EXPECT_EQ(OuterViewportScrollLayer()->scroll_tree_index(),
             host_impl_->CurrentlyScrollingNode()->id);
@@ -6011,10 +6265,13 @@
   scroll_delta = gfx::Vector2dF(0, 50);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
 
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ContentTopOffset());
   EXPECT_EQ(OuterViewportScrollLayer()->scroll_tree_index(),
@@ -6030,10 +6287,13 @@
   scroll_delta = gfx::Vector2dF(0, -65);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
 
   EXPECT_EQ(top_controls_height_,
             host_impl_->browser_controls_manager()->ContentTopOffset());
@@ -6050,12 +6310,13 @@
       layer_size_, layer_size_, layer_size_);
   DrawFrame();
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 
   host_impl_->browser_controls_manager()->ScrollBegin();
   host_impl_->browser_controls_manager()->ScrollBy(gfx::Vector2dF(0, 50));
@@ -6068,12 +6329,13 @@
 
   host_impl_->ScrollEnd();
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -25)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -25),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 
   float scroll_increment_y = -25;
   host_impl_->browser_controls_manager()->ScrollBegin();
@@ -6099,12 +6361,13 @@
   // Verify the layer is once-again non-scrollable.
   EXPECT_EQ(gfx::ScrollOffset(), InnerViewportScrollLayer()->MaxScrollOffset());
 
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
 }
 
 // Tests that activating a pending tree while there's a bounds_delta on the
@@ -6139,10 +6402,13 @@
 
     // Fully scroll the viewport.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(75, 75), gfx::Vector2dF(0, 2000)).get(),
+        BeginState(gfx::Point(75, 75), gfx::Vector2dF(0, 2000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2d(0, 2000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 2000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
   }
 
@@ -6255,13 +6521,17 @@
 
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
   EXPECT_TRUE(did_request_redraw_);
   EXPECT_TRUE(did_request_commit_);
@@ -6280,13 +6550,17 @@
 
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
   EXPECT_TRUE(did_request_redraw_);
   EXPECT_TRUE(did_request_commit_);
@@ -6302,7 +6576,8 @@
   // Scroll event is ignored because the input coordinate is outside the layer
   // boundaries.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(15, 5), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(15, 5), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
@@ -6328,7 +6603,8 @@
   // Scroll event is ignored because the scrollable layer is not facing the
   // viewer and there is nothing scrollable behind it.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
@@ -6356,7 +6632,8 @@
   // Scrolling fails because the content layer is asking to be scrolled on the
   // main thread.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
@@ -6378,10 +6655,13 @@
   gfx::ScrollOffset expected_max_scroll = outer_scroll->MaxScrollOffset();
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
 
   // Set new page scale from main thread.
@@ -6417,16 +6697,21 @@
   gfx::ScrollOffset expected_max_scroll = outer_scroll->MaxScrollOffset();
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
 
   // Set new page scale on impl thread by pinching.
   float page_scale = 2;
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
   host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -6472,8 +6757,10 @@
   UpdateDrawProperties(host_impl_->active_tree());
 
   // Set new page scale on impl thread by pinching.
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
   host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -6508,10 +6795,13 @@
   gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                         InputHandler::WHEEL)
+                                  .get(),
                               InputHandler::WHEEL)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
   host_impl_->ScrollEnd();
 
   float page_scale = 2;
@@ -6562,10 +6852,13 @@
     gfx::Vector2d scroll_delta(-8, -7);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                           InputHandler::WHEEL)
+                                    .get(),
                                 InputHandler::WHEEL)
                   .thread);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     host_impl_->ScrollEnd();
 
     std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -6614,11 +6907,13 @@
   viz::BeginFrameArgs begin_frame_args =
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(0, -100)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, -100),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100));
 
   begin_frame_args.frame_time = start_time;
@@ -6696,10 +6991,14 @@
     gfx::Vector2d scroll_delta(0, -10);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
                                 InputHandler::TOUCHSCREEN)
                   .thread);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     host_impl_->ScrollEnd();
 
     std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -6715,15 +7014,18 @@
 
     // The next time we scroll we should only scroll the parent.
     scroll_delta = gfx::Vector2d(0, -3);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               child_layer->scroll_tree_index());
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               child_layer->scroll_tree_index());
     host_impl_->ScrollEnd();
@@ -6743,15 +7045,18 @@
     // After scrolling the parent, another scroll on the opposite direction
     // should still scroll the child.
     scroll_delta = gfx::Vector2d(0, 7);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               grand_child_layer->scroll_tree_index());
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               grand_child_layer->scroll_tree_index());
     host_impl_->ScrollEnd();
@@ -6773,15 +7078,18 @@
     host_impl_->active_tree()->SetPageScaleOnActiveTree(2);
 
     scroll_delta = gfx::Vector2d(0, -2);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(1, 1), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(1, 1), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
     EXPECT_EQ(grand_child_layer->scroll_tree_index(),
               host_impl_->CurrentlyScrollingNode()->id);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     host_impl_->ScrollEnd();
 
     scroll_info = host_impl_->ProcessScrollDeltas();
@@ -6817,13 +7125,15 @@
         InputHandler::SCROLL_ON_IMPL_THREAD,
         host_impl_
             ->ScrollBegin(BeginState(gfx::Point(5, 5),
-                                     gfx::ScrollOffsetToVector2dF(scroll_delta))
+                                     gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                     InputHandler::WHEEL)
                               .get(),
                           InputHandler::WHEEL)
             .thread);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta))
-            .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(),
+                                     gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                     InputHandler::WHEEL)
+                             .get());
     host_impl_->ScrollEnd();
 
     std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -6858,13 +7168,15 @@
         InputHandler::SCROLL_ON_IMPL_THREAD,
         host_impl_
             ->ScrollBegin(BeginState(gfx::Point(5, 5),
-                                     gfx::ScrollOffsetToVector2dF(scroll_delta))
+                                     gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                     InputHandler::WHEEL)
                               .get(),
                           InputHandler::WHEEL)
             .thread);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta))
-            .get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(),
+                                     gfx::ScrollOffsetToVector2dF(scroll_delta),
+                                     InputHandler::WHEEL)
+                             .get());
     host_impl_->ScrollEnd();
 
     std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -6892,12 +7204,14 @@
   SetupViewportLayersNoScrolls(surface_size);
 
   // Scrolling should still work even though we did not draw yet.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
@@ -6914,13 +7228,16 @@
 
   // Scroll to the right in screen coordinates with a gesture.
   gfx::Vector2d gesture_scroll_delta(10, 0);
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gesture_scroll_delta).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gesture_scroll_delta).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gesture_scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gesture_scroll_delta, InputHandler::TOUCHSCREEN)
+          .get());
   host_impl_->ScrollEnd();
 
   // The layer should have scrolled down in its local coordinates.
@@ -6937,13 +7254,16 @@
             host_impl_
                 ->ScrollBegin(
                     BeginState(gfx::Point(),
-                               gfx::ScrollOffsetToVector2dF(wheel_scroll_delta))
+                               gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
+                               InputHandler::WHEEL)
                         .get(),
                     InputHandler::WHEEL)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(
-                                                     wheel_scroll_delta))
-                           .get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(),
+                  gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
+                  InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   // The layer should have scrolled down in its local coordinates.
@@ -6986,13 +7306,17 @@
   {
     // Scroll down in screen coordinates with a gesture.
     gfx::Vector2d gesture_scroll_delta(0, 10);
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_
-                  ->ScrollBegin(
-                      BeginState(gfx::Point(1, 1), gesture_scroll_delta).get(),
-                      InputHandler::TOUCHSCREEN)
-                  .thread);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), gesture_scroll_delta).get());
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point(1, 1), gesture_scroll_delta,
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN)
+            .thread);
+    host_impl_->ScrollBy(UpdateState(gfx::Point(), gesture_scroll_delta,
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     // The child layer should have scrolled down in its local coordinates an
@@ -7013,13 +7337,17 @@
     // Now reset and scroll the same amount horizontally.
     SetScrollOffsetDelta(child, gfx::Vector2dF());
     gfx::Vector2d gesture_scroll_delta(10, 0);
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_
-                  ->ScrollBegin(
-                      BeginState(gfx::Point(1, 1), gesture_scroll_delta).get(),
-                      InputHandler::TOUCHSCREEN)
-                  .thread);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), gesture_scroll_delta).get());
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point(1, 1), gesture_scroll_delta,
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN)
+            .thread);
+    host_impl_->ScrollBy(UpdateState(gfx::Point(), gesture_scroll_delta,
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     // The child layer should have scrolled down in its local coordinates an
@@ -7093,15 +7421,17 @@
     DrawFrame();
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(
-                      BeginState(viewport_point, gfx::ScrollOffsetToVector2dF(
-                                                     gesture_scroll_deltas[i]))
-                          .get(),
-                      InputHandler::TOUCHSCREEN)
+                  ->ScrollBegin(BeginState(viewport_point,
+                                           gfx::ScrollOffsetToVector2dF(
+                                               gesture_scroll_deltas[i]),
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
                   .thread);
     host_impl_->ScrollBy(
         UpdateState(viewport_point,
-                    gfx::ScrollOffsetToVector2dF(gesture_scroll_deltas[i]))
+                    gfx::ScrollOffsetToVector2dF(gesture_scroll_deltas[i]),
+                    InputHandler::TOUCHSCREEN)
             .get());
     viewport_point +=
         gfx::ScrollOffsetToFlooredVector2d(gesture_scroll_deltas[i]);
@@ -7133,10 +7463,13 @@
   gfx::Vector2d scroll_delta(0, 10);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   host_impl_->ScrollEnd();
 
   // The layer should have scrolled down in its local coordinates, but half the
@@ -7154,13 +7487,16 @@
             host_impl_
                 ->ScrollBegin(
                     BeginState(gfx::Point(),
-                               gfx::ScrollOffsetToVector2dF(wheel_scroll_delta))
+                               gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
+                               InputHandler::WHEEL)
                         .get(),
                     InputHandler::WHEEL)
                 .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(
-                                                     wheel_scroll_delta))
-                           .get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(),
+                  gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
+                  InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollEnd();
 
   // It should apply the scale factor to the scroll delta for the wheel event.
@@ -7238,8 +7574,10 @@
   // The pinch gesture doesn't put the delegate into a state where the scroll
   // offset is outside of the scroll range.  (this is verified by DCHECKs in the
   // delegate).
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, gfx::Point());
   host_impl_->PinchGestureUpdate(.5f, gfx::Point());
@@ -7252,18 +7590,22 @@
 
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
   host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
 
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
             scroll_watcher.last_set_scroll_offset());
 
   current_offset = gfx::ScrollOffset(42, 41);
   host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN).get());
   EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
             scroll_watcher.last_set_scroll_offset());
   host_impl_->ScrollEnd();
@@ -7458,14 +7800,16 @@
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
 
   // In-bounds scrolling does not affect overscroll.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::WHEEL)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_FALSE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
@@ -7473,7 +7817,8 @@
 
   // Overscroll events are reflected immediately.
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 50), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
@@ -7483,7 +7828,8 @@
 
   // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, -50)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -50), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_FALSE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
@@ -7492,7 +7838,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -10), InputHandler::WHEEL)
+          .get());
   EXPECT_FALSE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -7501,7 +7848,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(10, 0)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(10, 0), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_FALSE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
@@ -7510,7 +7858,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(-15, 0)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(-15, 0), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
@@ -7519,7 +7868,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, 60)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 60), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
@@ -7528,7 +7878,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(10, -60)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(10, -60), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -7539,7 +7890,8 @@
   // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
   // as no scroll occurs.
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, -20)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -20), InputHandler::WHEEL)
+          .get());
   EXPECT_FALSE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
@@ -7548,7 +7900,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, -20)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -20), InputHandler::WHEEL)
+          .get());
   EXPECT_FALSE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
@@ -7558,7 +7911,8 @@
 
   // Overscroll resets on valid scroll.
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_FALSE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
@@ -7567,7 +7921,8 @@
             host_impl_->accumulated_root_overscroll());
 
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, -20)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, -20), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -7609,11 +7964,14 @@
     gfx::Vector2d scroll_delta(0, -10);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
                                 InputHandler::TOUCHSCREEN)
                   .thread);
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               grand_child_layer->scroll_tree_index());
     EXPECT_TRUE(scroll_result.did_scroll);
@@ -7624,25 +7982,28 @@
     // The next time we scroll we should only scroll the parent, but overscroll
     // should still not reach the root layer.
     scroll_delta = gfx::Vector2d(0, -30);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               child_layer->scroll_tree_index());
     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
     host_impl_->ScrollEnd();
 
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
@@ -7653,16 +8014,18 @@
     // After scrolling the parent, another scroll on the opposite direction
     // should scroll the child.
     scroll_delta = gfx::Vector2d(0, 70);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
               grand_child_layer->scroll_tree_index());
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
@@ -7681,24 +8044,25 @@
   DrawFrame();
   {
     gfx::Vector2d scroll_delta(0, 8);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta).get(),
-                          InputHandler::WHEEL)
-            .thread);
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
+                                           InputHandler::WHEEL)
+                                    .get(),
+                                InputHandler::WHEEL)
+                  .thread);
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_TRUE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
-    scroll_result =
-        host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    scroll_result = host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     EXPECT_FALSE(scroll_result.did_scroll);
     EXPECT_TRUE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
@@ -7719,14 +8083,16 @@
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
 
   // Even though the layer can't scroll the overscroll still happens.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::WHEEL)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
   scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   EXPECT_FALSE(scroll_result.did_scroll);
   EXPECT_TRUE(scroll_result.did_overscroll_root);
   EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
@@ -7745,18 +8111,22 @@
     EXPECT_EQ(
         InputHandler::SCROLL_ON_IMPL_THREAD,
         host_impl_
-            ->ScrollBegin(
-                BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 100)).get(),
-                InputHandler::WHEEL)
+            ->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 100),
+                                     InputHandler::WHEEL)
+                              .get(),
+                          InputHandler::WHEEL)
             .thread);
     scroll_result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2dF(0, 100)).get());
+        UpdateState(gfx::Point(), gfx::Vector2dF(0, 100), InputHandler::WHEEL)
+            .get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF().ToString(),
               host_impl_->accumulated_root_overscroll().ToString());
-    scroll_result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2dF(0, -2.30f)).get());
+    scroll_result = host_impl_->ScrollBy(UpdateState(gfx::Point(),
+                                                     gfx::Vector2dF(0, -2.30f),
+                                                     InputHandler::WHEEL)
+                                             .get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -7764,21 +8134,27 @@
     host_impl_->ScrollEnd();
     // unusedrootDelta should be subtracted from applied delta so that
     // unwanted glow effect calls are not called.
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_
-                  ->ScrollBegin(
-                      BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 20)).get(),
-                      InputHandler::TOUCHSCREEN)
-                  .thread);
-    scroll_result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2dF(0, 20)).get());
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 20),
+                                     InputHandler::TOUCHSCREEN)
+                              .get(),
+                          InputHandler::TOUCHSCREEN)
+            .thread);
+    scroll_result =
+        host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 20),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get());
     EXPECT_TRUE(scroll_result.did_scroll);
     EXPECT_TRUE(scroll_result.did_overscroll_root);
     EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.000000f, 17.699997f),
                         host_impl_->accumulated_root_overscroll());
 
     scroll_result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f)).get());
+        UpdateState(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f),
+                    InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_FALSE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.000000f, 17.699997f),
@@ -7789,12 +8165,15 @@
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
                   ->ScrollBegin(
-                      BeginState(gfx::Point(0, 0), gfx::Vector2dF(-0.12f, 0.1f))
+                      BeginState(gfx::Point(0, 0), gfx::Vector2dF(-0.12f, 0.1f),
+                                 InputHandler::WHEEL)
                           .get(),
                       InputHandler::WHEEL)
                   .thread);
     scroll_result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f)).get());
+        UpdateState(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f),
+                    InputHandler::WHEEL)
+            .get());
     EXPECT_FALSE(scroll_result.did_scroll);
     EXPECT_FALSE(scroll_result.did_overscroll_root);
     EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -7820,10 +8199,13 @@
   // Start a scroll gesture, ensure it's scrolling the subscroller.
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100),
                      scroll_layer->CurrentScrollOffset());
@@ -7835,7 +8217,9 @@
   // doesn't consume the delta but it isn't counted as overscroll.
   {
     InputHandlerScrollResult result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(120, 140)).get());
+        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(120, 140),
+                    InputHandler::TOUCHSCREEN)
+            .get());
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200),
                      scroll_layer->CurrentScrollOffset());
@@ -7848,7 +8232,9 @@
   // doesn't consume the delta but it isn't counted as overscroll.
   {
     InputHandlerScrollResult result = host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(20, 40)).get());
+        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(20, 40),
+                    InputHandler::TOUCHSCREEN)
+            .get());
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200),
                      scroll_layer->CurrentScrollOffset());
@@ -7878,22 +8264,26 @@
   // Overscroll initiated outside layers will be handled by the main thread.
   EXPECT_EQ(nullptr, host_impl_->active_tree()->FindLayerThatIsHitByPoint(
                          gfx::PointF(0, 60)));
-  EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_MAIN_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
 
   // Overscroll initiated inside layers will be handled by the main thread.
   EXPECT_NE(nullptr, host_impl_->active_tree()->FindLayerThatIsHitByPoint(
                          gfx::PointF(0, 0)));
-  EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_MAIN_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
 }
 
 // Test that scrolling the inner viewport directly works, as can happen when the
@@ -7925,10 +8315,14 @@
   // Fully scroll the child.
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(1000, 1000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_EQ(1, host_impl_->active_tree()->CurrentTopControlsShownRatio());
@@ -7945,15 +8339,23 @@
   // should not be affected.
   {
     gfx::Vector2d scroll_delta(0, 10);
-    host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), scroll_delta).get(),
-                            InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(0, 0), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get(),
+        InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     EXPECT_EQ(0, host_impl_->active_tree()->CurrentTopControlsShownRatio());
     EXPECT_VECTOR_EQ(gfx::Vector2dF(),
                      inner_scroll_layer->CurrentScrollOffset());
 
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10),
                      inner_scroll_layer->CurrentScrollOffset());
@@ -7996,20 +8398,26 @@
   // viewport. The original outer viewport layer shouldn't get any scroll here.
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200, 200)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200),
                      child_scroll_layer->CurrentScrollOffset());
 
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200, 200)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
@@ -8024,10 +8432,13 @@
   // scrolling content as the outer viewport, it should stop chaining there.
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(),
@@ -8051,20 +8462,26 @@
   // layer).
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
                      inner_scroll_layer->CurrentScrollOffset());
 
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
@@ -8112,10 +8529,14 @@
   {
     // This should fully scroll the layer.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(1000, 1000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600),
@@ -8126,10 +8547,14 @@
     // Scrolling now should chain up but, since the outer viewport is a sibling
     // rather than an ancestor, we shouldn't chain to it.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(1000, 1000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600),
@@ -8156,8 +8581,9 @@
     // to keep the gesture anchored but not the outer or the sibling scroller.
     page_scale_factor = 2;
     gfx::Point anchor(viewport_size.width() / 2, viewport_size.height() / 2);
-    host_impl_->ScrollBegin(BeginState(anchor, gfx::Vector2dF()).get(),
-                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(
+        BeginState(anchor, gfx::Vector2dF(), InputHandler::TOUCHSCREEN).get(),
+        InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_factor, anchor);
     host_impl_->PinchGestureEnd(anchor, true);
@@ -8165,7 +8591,9 @@
     EXPECT_VECTOR_EQ(gfx::Vector2dF(anchor.x() / 2, anchor.y() / 2),
                      inner_scroll_layer->CurrentScrollOffset());
 
-    host_impl_->ScrollBy(UpdateState(anchor, viewport_size_vec).get());
+    host_impl_->ScrollBy(
+        UpdateState(anchor, viewport_size_vec, InputHandler::TOUCHSCREEN)
+            .get());
 
     EXPECT_VECTOR_EQ(ScaleVector2d(viewport_size_vec, 1 / page_scale_factor),
                      inner_scroll_layer->CurrentScrollOffset());
@@ -8192,10 +8620,14 @@
     // This should fully scroll the sibling but, because we latch to the
     // scroller, it shouldn't chain up to the inner viewport yet.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(2000, 2000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600),
@@ -8205,10 +8637,14 @@
 
     // Scrolling now should chain up to the inner viewport.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(2000, 2000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(ScaleVector2d(viewport_size_vec, 1 / page_scale_factor),
@@ -8218,10 +8654,14 @@
 
     // No more scrolling should be possible.
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0),
+                                     gfx::Vector2dF(2000, 2000),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(),
@@ -8250,22 +8690,26 @@
   // Overscroll initiated outside layers will be handled by the impl thread.
   EXPECT_EQ(nullptr, host_impl_->active_tree()->FindLayerThatIsHitByPoint(
                          gfx::PointF(0, 60)));
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
 
   // Overscroll initiated inside layers will be handled by the impl thread.
   EXPECT_NE(nullptr, host_impl_->active_tree()->FindLayerThatIsHitByPoint(
                          gfx::PointF(0, 0)));
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
 }
 
 class BlendStateCheckLayer : public LayerImpl {
@@ -9694,7 +10138,8 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
@@ -9728,7 +10173,8 @@
   DrawFrame();
 
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL)
+          .get(),
       InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
@@ -9749,12 +10195,13 @@
 
   // We should have scrolled |child_scroll| even though it does not move
   // any layer that is a drawn RSLL member.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::WHEEL)
-          .thread);
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
 
   EXPECT_EQ(child_scroll->scroll_tree_index(),
             host_impl_->CurrentlyScrollingNode()->id);
@@ -9935,16 +10382,18 @@
     SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
 
     // Scrolling normally should not trigger any forwarding.
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
-    EXPECT_TRUE(
-        host_impl_
-            ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
-            .did_scroll);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
+    EXPECT_TRUE(host_impl_
+                    ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+                                           InputHandler::TOUCHSCREEN)
+                                   .get())
+                    .did_scroll);
     host_impl_->ScrollEnd();
 
     EXPECT_EQ(0, set_needs_commit_count);
@@ -9953,16 +10402,18 @@
     // Scrolling with a scroll handler should defer the swap to the main
     // thread.
     host_impl_->active_tree()->set_have_scroll_event_handlers(true);
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                          InputHandler::TOUCHSCREEN)
-            .thread);
-    EXPECT_TRUE(
-        host_impl_
-            ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
-            .did_scroll);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
+                                InputHandler::TOUCHSCREEN)
+                  .thread);
+    EXPECT_TRUE(host_impl_
+                    ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+                                           InputHandler::TOUCHSCREEN)
+                                   .get())
+                    .did_scroll);
     host_impl_->ScrollEnd();
 
     EXPECT_EQ(0, set_needs_commit_count);
@@ -10058,18 +10509,22 @@
   // succeeds.
   const float residue = 10;
   float offset = top_controls_height_ - residue;
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, offset)).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
-  result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get());
+  result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
   EXPECT_TRUE(result.did_scroll);
   EXPECT_FLOAT_EQ(-offset,
@@ -10080,8 +10535,10 @@
   // Scroll across the boundary
   const float content_scroll = 20;
   offset = residue + content_scroll;
-  result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get());
+  result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_TRUE(result.did_scroll);
   EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
   EXPECT_EQ(-top_controls_height_,
@@ -10091,8 +10548,10 @@
 
   // Now scroll back to the top of the content
   offset = -content_scroll;
-  result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get());
+  result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_TRUE(result.did_scroll);
   EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
   EXPECT_EQ(-top_controls_height_,
@@ -10102,8 +10561,10 @@
 
   // And scroll the browser controls completely into view
   offset = -top_controls_height_;
-  result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get());
+  result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_TRUE(result.did_scroll);
   EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -10111,8 +10572,10 @@
             scroll_layer->CurrentScrollOffset().ToString());
 
   // And attempt to scroll past the end
-  result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get());
+  result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_FALSE(result.did_scroll);
   EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -10136,28 +10599,31 @@
   const float delta = top_controls_height_;
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, delta)).get(),
-                    InputHandler::WHEEL)
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, delta),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
                 .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
 
   // Wheel scrolls should not affect the browser controls, and should pass
   // directly through to the viewport.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta),
+                                         InputHandler::WHEEL)
+                                 .get())
+                  .did_scroll);
   EXPECT_FLOAT_EQ(0,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta),
                    viewport_layer->CurrentScrollOffset());
 
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta),
+                                         InputHandler::WHEEL)
+                                 .get())
+                  .did_scroll);
   EXPECT_FLOAT_EQ(0,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2),
@@ -10176,21 +10642,24 @@
 
   const float residue = 35;
   float offset = top_controls_height_ - residue;
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, offset)).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
   // Scroll the browser controls partially.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
   EXPECT_FLOAT_EQ(-offset,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -10263,21 +10732,24 @@
 
   const float residue = 15;
   float offset = top_controls_height_ - residue;
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, offset)).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
   // Scroll the browser controls partially.
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
   EXPECT_FLOAT_EQ(-offset,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
@@ -10337,34 +10809,39 @@
   DrawFrame();
 
   float offset = 50;
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, offset)).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
+                                   InputHandler::TOUCHSCREEN)
+                            .get(),
+                        InputHandler::TOUCHSCREEN)
+          .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
 
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
   EXPECT_EQ(-offset,
             host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
-  EXPECT_TRUE(
-      host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
-          .did_scroll);
+  EXPECT_TRUE(host_impl_
+                  ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+                                         InputHandler::TOUCHSCREEN)
+                                 .get())
+                  .did_scroll);
 
   // Should have fully scrolled
   EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
@@ -10375,7 +10852,8 @@
   // Overscroll the content
   EXPECT_FALSE(host_impl_
                    ->ScrollBy(UpdateState(gfx::Point(),
-                                          gfx::Vector2d(0, overscrollamount))
+                                          gfx::Vector2d(0, overscrollamount),
+                                          InputHandler::TOUCHSCREEN)
                                   .get())
                    .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
@@ -10385,8 +10863,9 @@
 
   EXPECT_TRUE(
       host_impl_
-          ->ScrollBy(
-              UpdateState(gfx::Point(), gfx::Vector2d(0, -2 * offset)).get())
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -2 * offset),
+                                 InputHandler::TOUCHSCREEN)
+                         .get())
           .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
@@ -10395,7 +10874,9 @@
 
   EXPECT_TRUE(
       host_impl_
-          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -offset)).get())
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -offset),
+                                 InputHandler::TOUCHSCREEN)
+                         .get())
           .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
@@ -10443,10 +10924,13 @@
   // original outer viewport should get no scroll.
   {
     host_impl_->ScrollBegin(
-        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get(),
+        BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                   InputHandler::TOUCHSCREEN)
+            .get(),
         InputHandler::TOUCHSCREEN);
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     host_impl_->ScrollEnd();
 
     EXPECT_VECTOR_EQ(gfx::Vector2dF(), outer_scroll->CurrentScrollOffset());
@@ -10514,13 +10998,17 @@
     // Make sure the scroll goes to the inner viewport first.
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                           InputHandler::TOUCHSCREEN)
+                                    .get(),
                                 InputHandler::TOUCHSCREEN)
                   .thread);
     EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
 
     // Scroll near the edge of the outer viewport.
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::TOUCHSCREEN)
+            .get());
     inner_expected += scroll_delta;
     EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
 
@@ -10530,8 +11018,10 @@
     // Now diagonal scroll across the outer viewport boundary in a single event.
     // The entirety of the scroll should be consumed, as bubbling between inner
     // and outer viewport layers is perfect.
-    host_impl_->ScrollBy(
-        UpdateState(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2)).get());
+    host_impl_->ScrollBy(UpdateState(gfx::Point(),
+                                     gfx::ScaleVector2d(scroll_delta, 2),
+                                     InputHandler::TOUCHSCREEN)
+                             .get());
     EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
     outer_expected += scroll_delta;
     inner_expected += scroll_delta;
@@ -10559,21 +11049,24 @@
   UpdateDrawProperties(host_impl_->active_tree());
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->RootScrollBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                    InputHandler::TOUCHSCREEN)
-                .thread);
-  EXPECT_EQ(host_impl_->CurrentlyScrollingNode(),
-            host_impl_->OuterViewportScrollNode());
-  host_impl_->ScrollEnd();
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
       host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::TOUCHSCREEN)
+          ->RootScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                       InputHandler::TOUCHSCREEN)
+                                .get(),
+                            InputHandler::TOUCHSCREEN)
           .thread);
+  EXPECT_EQ(host_impl_->CurrentlyScrollingNode(),
+            host_impl_->OuterViewportScrollNode());
+  host_impl_->ScrollEnd();
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
   EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
             child_scroll->scroll_tree_index());
   host_impl_->ScrollEnd();
@@ -10596,14 +11089,17 @@
 
   // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 100)).get(),
-                        InputHandler::TOUCHSCREEN)
-          .thread);
-  scroll_result = host_impl_->ScrollBy(
-      UpdateState(gfx::Point(), gfx::Vector2dF(0, 100)).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 100),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
+                              InputHandler::TOUCHSCREEN)
+                .thread);
+  scroll_result =
+      host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 100),
+                                       InputHandler::TOUCHSCREEN)
+                               .get());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
 
   // When inner viewport is unscrollable, a fling gives zero overscroll.
@@ -10993,11 +11489,13 @@
         new SimpleSwapPromiseMonitor(nullptr, host_impl_.get(),
                                      &set_needs_commit_count,
                                      &set_needs_redraw_count));
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_
-                  ->ScrollAnimatedBegin(
-                      BeginState(gfx::Point(), gfx::Vector2d(0, 50)).get())
-                  .thread);
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
+                                             InputHandler::WHEEL)
+                                      .get())
+            .thread);
     host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50));
 
     EXPECT_EQ(0, set_needs_commit_count);
@@ -11093,7 +11591,8 @@
   // Start an animated scroll over the outer viewport.
   {
     gfx::Point position(40, 40);
-    auto begin_state = BeginState(position, gfx::Vector2d(0, 50));
+    auto begin_state =
+        BeginState(position, gfx::Vector2d(0, 50), InputHandler::WHEEL);
     host_impl_->ScrollAnimatedBegin(begin_state.get());
     host_impl_->ScrollAnimated(position, gfx::Vector2d(0, 50));
     EXPECT_EQ(outer_scroll->scroll_tree_index(),
@@ -11137,7 +11636,8 @@
   // because we don't clear the latch until the animation is finished.
   {
     gfx::Point position(10, 10);
-    auto begin_state = BeginState(position, gfx::Vector2d(0, 50));
+    auto begin_state =
+        BeginState(position, gfx::Vector2d(0, 50), InputHandler::WHEEL);
     host_impl_->ScrollAnimatedBegin(begin_state.get());
     EXPECT_EQ(outer_scroll->scroll_tree_index(),
               host_impl_->CurrentlyScrollingNode()->id);
@@ -11192,12 +11692,13 @@
   // afterwards. This will ensure we test both the starting animation and
   // animation update code.
   {
-    EXPECT_EQ(
-        InputHandler::SCROLL_ON_IMPL_THREAD,
-        host_impl_
-            ->ScrollAnimatedBegin(
-                BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 10)).get())
-            .thread);
+    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+              host_impl_
+                  ->ScrollAnimatedBegin(BeginState(gfx::Point(10, 10),
+                                                   gfx::Vector2d(0, 10),
+                                                   InputHandler::WHEEL)
+                                            .get())
+                  .thread);
     host_impl_->ScrollAnimated(gfx::Point(10, 10), gfx::Vector2d(0, 10));
     host_impl_->ScrollAnimated(gfx::Point(10, 10), gfx::Vector2d(0, 20));
 
@@ -11273,7 +11774,8 @@
   scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0));
 
   host_impl_->ScrollBegin(
-      BeginState(gfx::Point(350, 18), gfx::Vector2dF()).get(),
+      BeginState(gfx::Point(350, 18), gfx::Vector2dF(), InputHandler::SCROLLBAR)
+          .get(),
       InputHandler::SCROLLBAR);
   TestInputHandlerClient input_handler_client;
   host_impl_->BindToClient(&input_handler_client);
@@ -11330,20 +11832,24 @@
   const gfx::Size viewport_size(50, 100);
   SetupViewportLayersOuterScrolls(viewport_size, content_size);
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
 
   host_impl_->ScrollEnd();
 
   // The second ScrollAnimatedBegin should not get ignored.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
 }
 
 // Verfify that a smooth scroll animation doesn't jump when UpdateTarget gets
@@ -11366,11 +11872,13 @@
   host_impl_->UpdateAnimationState(true);
   host_impl_->DidFinishImplFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(0, 50)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50));
   // This will call ScrollOffsetAnimationCurve::UpdateTarget while the animation
   // created above is in state ANIMATION::WAITING_FOR_TARGET_AVAILABILITY and
@@ -11415,11 +11923,13 @@
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Create animation with a 100ms delay.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(0, 100)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 100),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 100),
                              base::TimeDelta::FromMilliseconds(100));
 
@@ -11477,11 +11987,13 @@
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Perform animated scroll.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(0, 50)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50));
 
   LayerImpl* scrolling_layer = OuterViewportScrollLayer();
@@ -11511,15 +12023,18 @@
   EXPECT_TRUE(y > 1 && y < 49);
 
   // Perform instant scroll.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollBegin(
-                    BeginState(gfx::Point(0, y), gfx::Vector2dF(0, 50)).get(),
-                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, y), gfx::Vector2dF(0, 50),
+                                   InputHandler::WHEEL)
+                            .get(),
+                        InputHandler::WHEEL)
+          .thread);
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y)));
   host_impl_->ScrollBy(
-      UpdateState(gfx::Point(0, y), gfx::Vector2d(0, 50)).get());
+      UpdateState(gfx::Point(0, y), gfx::Vector2d(0, 50), InputHandler::WHEEL)
+          .get());
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y + 50)));
   host_impl_->ScrollEnd();
   EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
@@ -11549,11 +12064,13 @@
   viz::BeginFrameArgs begin_frame_args =
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(0, 50)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50));
 
   LayerImpl* scrolling_layer = OuterViewportScrollLayer();
@@ -11635,11 +12152,13 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(250);
   viz::BeginFrameArgs begin_frame_args =
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(10, 20)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(10, 20),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(10, 20));
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -11725,11 +12244,13 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(50);
   viz::BeginFrameArgs begin_frame_args =
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(90, 90)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(90, 90),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(90, 90));
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -11785,11 +12306,13 @@
   viz::BeginFrameArgs begin_frame_args =
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_
-                ->ScrollAnimatedBegin(
-                    BeginState(gfx::Point(), gfx::Vector2d(50, 50)).get())
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollAnimatedBegin(BeginState(gfx::Point(), gfx::Vector2d(50, 50),
+                                           InputHandler::WHEEL)
+                                    .get())
+          .thread);
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(50, 50));
 
   EXPECT_EQ(scrolling_layer->scroll_tree_index(),
@@ -11869,7 +12392,8 @@
       viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   host_impl_->ScrollAnimatedBegin(
-      BeginState(gfx::Point(), gfx::Vector2d(500, 500)).get());
+      BeginState(gfx::Point(), gfx::Vector2d(500, 500), InputHandler::WHEEL)
+          .get());
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(500, 500));
 
   EXPECT_EQ(scrolling_layer->scroll_tree_index(),
@@ -11984,8 +12508,10 @@
     SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
 
     float page_scale_delta = 2;
-    host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                            InputHandler::TOUCHSCREEN);
+    host_impl_->ScrollBegin(
+        BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+            .get(),
+        InputHandler::TOUCHSCREEN);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
     host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -11994,12 +12520,15 @@
     gfx::Vector2dF scroll_delta(0, 5);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_
-                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta).get(),
+                  ->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
+                                           InputHandler::WHEEL)
+                                    .get(),
                                 InputHandler::WHEEL)
                   .thread);
     EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
 
-    host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
+    host_impl_->ScrollBy(
+        UpdateState(gfx::Point(), scroll_delta, InputHandler::WHEEL).get());
     host_impl_->ScrollEnd();
     EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
                      scroll_layer->CurrentScrollOffset());
@@ -13036,13 +13565,16 @@
   }
 
   // Scrolling should update metadata immediately.
-  EXPECT_EQ(
-      InputHandler::SCROLL_ON_IMPL_THREAD,
-      host_impl_
-          ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10)).get(),
-                        InputHandler::WHEEL)
-          .thread);
-  host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
+  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+            host_impl_
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+                                         InputHandler::WHEEL)
+                                  .get(),
+                              InputHandler::WHEEL)
+                .thread);
+  host_impl_->ScrollBy(
+      UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL)
+          .get());
   {
     RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata();
     EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset);
@@ -13103,8 +13635,10 @@
 #endif
 
   // Page scale should update metadata correctly (shrinking only the viewport).
-  host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
-                          InputHandler::TOUCHSCREEN);
+  host_impl_->ScrollBegin(
+      BeginState(gfx::Point(), gfx::Vector2dF(), InputHandler::TOUCHSCREEN)
+          .get(),
+      InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, gfx::Point());
   host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -13258,10 +13792,12 @@
     // If the test leg contains a scroll, perform it.
     if (!test_leg.scroll_delta.IsZero()) {
       host_impl_->ScrollBegin(
-          BeginState(gfx::Point(), test_leg.scroll_delta).get(),
+          BeginState(gfx::Point(), test_leg.scroll_delta, InputHandler::WHEEL)
+              .get(),
           InputHandler::WHEEL);
       host_impl_->ScrollBy(
-          UpdateState(gfx::Point(), test_leg.scroll_delta).get());
+          UpdateState(gfx::Point(), test_leg.scroll_delta, InputHandler::WHEEL)
+              .get());
     }
 
     // Trigger draw.
@@ -13292,7 +13828,9 @@
 
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_
-                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF()).get(),
+                ->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+                                         InputHandler::TOUCHSCREEN)
+                                  .get(),
                               InputHandler::TOUCHSCREEN)
                 .thread);
 
@@ -13716,7 +14254,9 @@
   // should result in scrolling the scroll layer on the impl thread as the
   // scrollbar should not be hit.
   InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
-      BeginState(gfx::Point(350, 50), gfx::Vector2dF(0, 10)).get(),
+      BeginState(gfx::Point(350, 50), gfx::Vector2dF(0, 10),
+                 InputHandler::TOUCHSCREEN)
+          .get(),
       InputHandler::TOUCHSCREEN);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 872bd6cd..ea27187 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=81
 MINOR=0
-BUILD=4018
+BUILD=4020
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 787ee20c..04fede7 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -51,6 +51,8 @@
     "$target_gen_dir/trichrome_library_64_32_apk/AndroidManifest.xml"
 trichrome_library_64_android_manifest =
     "$target_gen_dir/trichrome_library_64_apk/AndroidManifest.xml"
+trichrome_library_32_android_manifest =
+    "$target_gen_dir/trichrome_library_32_apk/AndroidManifest.xml"
 
 app_hooks_impl = "java/src/org/chromium/chrome/browser/AppHooksImpl.java"
 _chrome_version_java_file = "$target_gen_dir/templates/org/chromium/chrome/browser/ChromeVersionConstants.java"
@@ -110,6 +112,14 @@
                   "manifest_package=$trichrome_library_package",
                 ]
   }
+  jinja_template("trichrome_library_32_android_manifest") {
+    input = "java/AndroidManifest_trichrome_library.xml"
+    output = trichrome_library_32_android_manifest
+    variables = trichrome_jinja_variables + [
+                  "trichrome_version=$trichrome_32_version_code",
+                  "manifest_package=$trichrome_library_package",
+                ]
+  }
 }
 
 generate_ui_locale_resources("ui_locale_string_resources") {
@@ -1123,9 +1133,9 @@
 }
 
 android_resources("product_version_resources") {
-  resource_dirs = []
-  generated_resource_dirs = [ version_resource_dir ]
-  generated_resource_files = [ version_resource_file ]
+  sources = [
+    version_resource_file,
+  ]
   custom_package = "org.chromium.base"
   deps = [
     ":version_xml",
@@ -1861,6 +1871,14 @@
   }
 
   if (android_64bit_target_cpu) {
+    trichrome_library_apk_tmpl("trichrome_library_32_apk") {
+      apk_name = "TrichromeLibrary32"
+      android_manifest = trichrome_library_32_android_manifest
+      android_manifest_dep = ":trichrome_library_32_android_manifest"
+      is_64_bit_browser = false
+      include_64_bit_webview = false
+    }
+
     trichrome_library_apk_tmpl("trichrome_library_64_32_apk") {
       apk_name = "TrichromeLibrary6432"
       android_manifest = trichrome_library_64_32_android_manifest
@@ -2547,6 +2565,12 @@
   }
 
   if (android_64bit_target_cpu) {
+    monochrome_or_trichrome_public_bundle_tmpl("monochrome_32_public_bundle") {
+      bundle_suffix = "32"
+      is_64_bit_browser = false
+      include_64_bit_webview = false
+    }
+
     monochrome_or_trichrome_public_bundle_tmpl("monochrome_64_public_bundle") {
       bundle_suffix = "64"
       is_64_bit_browser = true
@@ -2576,6 +2600,14 @@
       use_trichrome_library = true
       static_library_provider = ":trichrome_library_64_32_apk"
     }
+
+    monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_32_bundle") {
+      bundle_suffix = "32"
+      is_64_bit_browser = false
+      include_64_bit_webview = false
+      use_trichrome_library = true
+      static_library_provider = ":trichrome_library_32_apk"
+    }
   }
 }
 
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 4074377..47e5553 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1736,6 +1736,11 @@
   "java/src/org/chromium/chrome/browser/toolbar/top/IncognitoSwitchCoordinator.java",
   "java/src/org/chromium/chrome/browser/toolbar/top/IncognitoSwitchProperties.java",
   "java/src/org/chromium/chrome/browser/toolbar/top/IncognitoSwitchViewBinder.java",
+  "java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java",
+  "java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java",
+  "java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java",
+  "java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java",
+  "java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java",
   "java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java",
   "java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinatorPhone.java",
   "java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 29cf494a..41fbc30 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -72,7 +72,10 @@
   _is_modern = defined(invoker.is_modern) && invoker.is_modern
   _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
   _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
+  _is_64_bit_browser =
+      defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser
   assert(_is_modern || !_is_modern)  # Mark as used.
+  assert(_is_64_bit_browser || !_is_64_bit_browser)  # Mark as used.
   assert(!(_is_monochrome && _is_trichrome),
          "Cannot be both trichrome and monochrome!")
 
@@ -86,7 +89,9 @@
         target_cpu == "arm" || (_is_monochrome && target_cpu == "arm64")
     _add_unwind_tables =
         _needs_32bit_lib && _add_unwind_tables_in_chrome_32bit_apk &&
-        defined(invoker.shared_libraries)
+        ((android_64bit_target_cpu &&
+          defined(invoker.secondary_abi_shared_libraries)) ||
+         (!android_64bit_target_cpu && defined(invoker.shared_libraries)))
   }
 
   if (_add_unwind_tables) {
@@ -99,11 +104,21 @@
       if (defined(invoker.shared_library_for_unwind_asset)) {
         library_target = invoker.shared_library_for_unwind_asset
       } else {
-        library_target = "chrome"
+        if (_is_monochrome || _is_trichrome) {
+          library_target = "monochrome"
+        } else {
+          library_target = "chrome"
+        }
       }
-      deps = invoker.shared_libraries
-      if (defined(android_secondary_abi_cpu)) {
-        deps += [ "//chrome/android:lib${library_target}($android_secondary_abi_toolchain)" ]
+
+      if (android_64bit_target_cpu) {
+        deps = [
+          "//chrome/android:lib${library_target}($android_secondary_abi_toolchain)",
+        ]
+      } else {
+        deps = [
+          "//chrome/android:lib${library_target}",
+        ]
       }
     }
   } else if (defined(invoker.shared_library_for_unwind_asset)) {
@@ -312,6 +327,7 @@
                            [
                              "failed_manifest_expectation_file",
                              "failed_proguard_expectation_file",
+                             "is_64_bit_browser",
                              "version_code",
                              "verify_manifest",
                            ])
@@ -365,10 +381,7 @@
         _include_primary_support = true
       }
 
-      shared_library_for_unwind_asset = "monochrome"
-
       _deps += [
-        "//android_webview:monochrome_webview_assets",
         "//android_webview/glue",
         "//android_webview/nonembedded:nonembedded_java",
         "//chrome/android:monochrome_java",
@@ -381,18 +394,27 @@
 
       if (_include_primary_support) {
         _deps += [
+          "//android_webview:monochrome_webview_primary_abi_assets",
           "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
         ]
         loadable_modules +=
             [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
       }
       if (_include_secondary_support) {
-        _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
-        _deps += [ _trampoline ]
+        _trampoline =
+            "//third_party/crashpad/crashpad/handler:" +
+            "crashpad_handler_trampoline($android_secondary_abi_toolchain)"
+
+        _deps += [
+          "//android_webview:monochrome_webview_secondary_abi_assets",
+          _trampoline,
+        ]
+
         _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
         secondary_abi_loadable_modules +=
             [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
       }
+
       alternative_android_sdk_dep = webview_framework_dep
       app_as_shared_lib = true
       _pak_prefix = "monochrome"
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 cee00b7..6b77a8e 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
@@ -44,10 +44,10 @@
 import org.chromium.chrome.browser.signin.PersonalizedSigninPromoView;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.ui.widget.displaystyle.ViewResizer;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.feed.R;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.ViewResizer;
 import org.chromium.ui.UiUtils;
 
 import java.util.Arrays;
diff --git a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
index da65568..046cf2e0 100644
--- a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
+++ b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
@@ -19,6 +19,7 @@
     <org.chromium.chrome.browser.toolbar.HomeButton
         android:id="@+id/home_button"
         app:tint="@color/standard_mode_tint"
+        android:background="?attr/selectableItemBackgroundBorderless"
         android:contentDescription="@string/accessibility_toolbar_btn_home"
         style="@style/SplitToolbarButton" />
 
@@ -29,6 +30,7 @@
         android:src="@drawable/ic_share_white_24dp"
         app:tint="@color/standard_mode_tint"
         android:contentDescription="@string/share"
+        android:background="?attr/selectableItemBackgroundBorderless"
         style="@style/SplitToolbarButton" />
 
     <include layout="@layout/toolbar_space" />
@@ -51,6 +53,7 @@
         android:id="@+id/tab_switcher_button"
         style="@style/SplitToolbarButton"
         app:menuMaxWidth="@dimen/tab_switcher_menu_width"
+        android:background="?attr/selectableItemBackgroundBorderless"
         android:contentDescription="@string/accessibility_toolbar_btn_tabswitcher_toggle_default"
         app:menuVerticalOverlapAnchor="false" />
 
diff --git a/chrome/android/java/res/layout/bottom_toolbar_menu_button.xml b/chrome/android/java/res/layout/bottom_toolbar_menu_button.xml
index 15c5340..47f073e6 100644
--- a/chrome/android/java/res/layout/bottom_toolbar_menu_button.xml
+++ b/chrome/android/java/res/layout/bottom_toolbar_menu_button.xml
@@ -15,21 +15,19 @@
 
     <org.chromium.ui.widget.ChromeImageButton
         android:id="@+id/menu_button"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:background="@null"
+        style="@style/SplitToolbarButton"
         android:src="@drawable/ic_more_vert_24dp"
         android:importantForAccessibility="no"
         android:layout_gravity="center"
+        android:background="?attr/selectableItemBackgroundBorderless"
         app:tint="@color/standard_mode_tint" />
 
     <ImageView
         android:id="@+id/menu_badge"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:background="@null"
+        style="@style/SplitToolbarButton"
         android:src="@drawable/badge_update_dark"
         tools:ignore="ContentDescription"
+        android:background="?attr/selectableItemBackgroundBorderless"
         android:importantForAccessibility="no"
         android:layout_gravity="center"
         android:visibility="invisible" />
diff --git a/chrome/android/java/res/layout/start_top_toolbar.xml b/chrome/android/java/res/layout/start_top_toolbar.xml
new file mode 100644
index 0000000..f2d2d80
--- /dev/null
+++ b/chrome/android/java/res/layout/start_top_toolbar.xml
@@ -0,0 +1,56 @@
+<?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.toolbar.top.StartSurfaceToolbarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/tab_switcher_toolbar"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/toolbar_height_no_shadow"
+    android:clickable="true" >
+
+    <Switch
+        android:id="@+id/incognito_switch"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentStart="true"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:thumb="@drawable/incognito_switch"
+        android:track="@drawable/incognito_switch_track"
+        android:visibility="gone"/>
+
+    <ImageView
+        android:id="@+id/logo"
+        android:layout_width="wrap_content"
+        android:layout_height="32dp"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:scaleType="centerInside"
+        app:srcCompat="@drawable/google_logo"
+        android:visibility="gone"
+        android:contentDescription="@null"/>
+
+    <org.chromium.chrome.browser.toolbar.NewTabButton
+        android:id="@+id/new_tab_button"
+        style="@style/ToolbarButton"
+        android:layout_width="wrap_content"
+        android:layout_toStartOf="@+id/menu_anchor"
+        android:layout_centerVertical="true"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:contentDescription="@string/accessibility_toolbar_btn_new_tab" />
+
+    <FrameLayout
+      android:id="@+id/menu_anchor"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:layout_alignParentEnd="true"
+      android:layout_alignParentStart="false">
+      <include layout="@layout/menu_button"/>
+    </FrameLayout>
+
+</org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarView>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 5db2a3b..86718757 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -269,7 +269,6 @@
             "SearchEnginePromo.ExistingDevice";
     public static final String SEARCH_ENGINE_PROMO_NEW_DEVICE = "SearchEnginePromo.NewDevice";
     public static final String MARK_HTTP_AS = "MarkHttpAs";
-    // TODO(crbug.com/980849) Remove ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY
     public static final String MOBILE_IDENTITY_CONSISTENCY = "MobileIdentityConsistency";
     public static final String MODAL_PERMISSION_PROMPTS = "ModalPermissionPrompts";
     public static final String MODAL_PERMISSION_DIALOG_VIEW = "ModalPermissionDialogView";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobService.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobService.java
index 14d9634..02f87ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobService.java
@@ -7,9 +7,9 @@
 import android.os.Build;
 import android.os.PersistableBundle;
 
+import org.chromium.components.minidump_uploader.MinidumpUploadJob;
+import org.chromium.components.minidump_uploader.MinidumpUploadJobImpl;
 import org.chromium.components.minidump_uploader.MinidumpUploadJobService;
-import org.chromium.components.minidump_uploader.MinidumpUploader;
-import org.chromium.components.minidump_uploader.MinidumpUploaderImpl;
 
 /**
  * Class that interacts with the Android JobScheduler to upload minidumps at appropriate times.
@@ -17,7 +17,7 @@
 @TargetApi(Build.VERSION_CODES.M)
 public class ChromeMinidumpUploadJobService extends MinidumpUploadJobService {
     @Override
-    protected MinidumpUploader createMinidumpUploader(PersistableBundle permissions) {
-        return new MinidumpUploaderImpl(new ChromeMinidumpUploaderDelegate(this, permissions));
+    protected MinidumpUploadJob createMinidumpUploadJob(PersistableBundle permissions) {
+        return new MinidumpUploadJobImpl(new ChromeMinidumpUploaderDelegate(this, permissions));
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
index c3428d39..3f96f82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
@@ -23,8 +23,8 @@
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
 import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator.DateOrderedListObserver;
 import org.chromium.chrome.browser.download.home.list.holder.ListItemViewHolder;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.ui.modelutil.ForwardingListObservable;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 import org.chromium.ui.modelutil.RecyclerViewAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java
index 557208b..4b8e87cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java
@@ -11,9 +11,9 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.download.home.list.ListItem;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.widget.selection.SelectableListToolbar;
 import org.chromium.chrome.download.R;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 import java.util.List;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
index 76e1fa4..2b614f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -52,10 +52,10 @@
 import org.chromium.chrome.browser.suggestions.tile.TileGridLayout;
 import org.chromium.chrome.browser.suggestions.tile.TileGroup;
 import org.chromium.chrome.browser.suggestions.tile.TileRenderer;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.browser.vr.VrModeObserver;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.ui.base.DeviceFormFactor;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index d1ca3eb..07ade39c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -32,9 +32,9 @@
 import org.chromium.chrome.browser.suggestions.tile.TileGroup;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.ui.widget.displaystyle.ViewResizer;
 import org.chromium.chrome.browser.util.ViewUtils;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.ViewResizer;
 
 /**
  * The native new tab page, represented by some basic data such as title and url, and an Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
index 340f3ba..3b42fdf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
@@ -21,7 +21,7 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
index 22d10e44..815b21f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
@@ -16,8 +16,8 @@
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.native_page.ContextMenuManager.ContextMenuItemId;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 /**
  * Holder for a generic card.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index 02aa5ec..a5681ff0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -32,7 +32,7 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.modelutil.ListObservable;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/PersonalizedPromoViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/PersonalizedPromoViewHolder.java
index c248191..d510f35 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/PersonalizedPromoViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/PersonalizedPromoViewHolder.java
@@ -15,7 +15,7 @@
 import org.chromium.chrome.browser.signin.SigninPromoController;
 import org.chromium.chrome.browser.signin.SigninPromoUtil;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 /**
  * View Holder for {@link SignInPromo} if the personalized promo is to be shown.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusCardViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusCardViewHolder.java
index bcd23731..6c2d15618 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusCardViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusCardViewHolder.java
@@ -17,7 +17,7 @@
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.suggestions.SuggestionsMetrics;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 /**
  * ViewHolder for Status and Promo cards.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderViewHolder.java
index e7f6dc2..d4de082 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderViewHolder.java
@@ -10,7 +10,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 /**
  * View holder for the header of a section of cards.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
index 287005d..ee24ef7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -22,8 +22,8 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsOfflineModelObserver;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.DisplayStyleObserverAdapter;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.DisplayStyleObserverAdapter;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.ui.mojom.WindowOpenDisposition;
 
 /**
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 77c56068..6d557f78 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
@@ -65,9 +65,10 @@
                                               PaymentHandlerToolbarMediator.MINIMUM_LOAD_PROGRESS)
                                       .with(PaymentHandlerToolbarProperties.SECURITY_ICON,
                                               ConnectionSecurityLevel.NONE)
+                                      .with(PaymentHandlerToolbarProperties.URL, url)
                                       .build();
         PaymentHandlerToolbarMediator mediator =
-                new PaymentHandlerToolbarMediator(model, webContents, url, observer);
+                new PaymentHandlerToolbarMediator(model, webContents, observer);
         webContents.addObserver(mediator);
         PropertyModelChangeProcessor changeProcessor = PropertyModelChangeProcessor.create(
                 model, mToolbarView, PaymentHandlerToolbarViewBinder::bind);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediator.java
index ee41a73..b1f0e6d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediator.java
@@ -12,7 +12,6 @@
 import org.chromium.chrome.browser.payments.handler.toolbar.PaymentHandlerToolbarCoordinator.PaymentHandlerToolbarObserver;
 import org.chromium.chrome.browser.ssl.SecurityStateModel;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
-import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
@@ -48,29 +47,14 @@
      * @param model The {@link PaymentHandlerToolbarProperties} that holds all the view state for
      *         the payment handler toolbar component.
      * @param webContents The web-contents that loads the payment app.
-     * @param url The url of the payment handler app.
      * @param observer The observer of this toolbar.
      */
-    /* package */ PaymentHandlerToolbarMediator(PropertyModel model, WebContents webContents,
-            URI url, PaymentHandlerToolbarObserver observer) {
+    /* package */ PaymentHandlerToolbarMediator(
+            PropertyModel model, WebContents webContents, PaymentHandlerToolbarObserver observer) {
         super(webContents);
         mWebContentsRef = webContents;
         mModel = model;
         mObserver = observer;
-
-        formatUrlAndUpdateProperty(url.toString());
-    }
-
-    /** Format the url for displaying purpose and update the origin in the property model. */
-    private void formatUrlAndUpdateProperty(String url) {
-        String origin = UrlFormatter.formatUrlForSecurityDisplayOmitScheme(url);
-        try {
-            mModel.set(PaymentHandlerToolbarProperties.ORIGIN, new URI(origin));
-        } catch (URISyntaxException e) {
-            Log.e(TAG, "Failed to instantiate URI with the origin \"%s\", whose url is \"%s\".",
-                    origin, url);
-            mObserver.onToolbarError();
-        }
     }
 
     // WebContentsObserver:
@@ -94,9 +78,15 @@
 
     @Override
     public void didFinishNavigation(NavigationHandle navigation) {
-        if (navigation.hasCommitted() && navigation.isInMainFrame()) {
-            mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, false);
-            formatUrlAndUpdateProperty(navigation.getUrl());
+        if (!navigation.hasCommitted() || !navigation.isInMainFrame()) return;
+        mModel.set(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, false);
+
+        String url = navigation.getUrl();
+        try {
+            mModel.set(PaymentHandlerToolbarProperties.URL, new URI(url));
+        } catch (URISyntaxException e) {
+            Log.e(TAG, "Failed to instantiate a URI with the url \"%s\".", url);
+            mObserver.onToolbarError();
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarProperties.java
index 6b76baf..31cfa1cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarProperties.java
@@ -14,7 +14,7 @@
 
 /** PaymentHandlerToolbar UI properties, which fully describe the state of the UI. */
 /* package */ class PaymentHandlerToolbarProperties {
-    /* package */ static final WritableObjectPropertyKey<URI> ORIGIN =
+    /* package */ static final WritableObjectPropertyKey<URI> URL =
             new WritableObjectPropertyKey<>();
 
     /* package */ static final WritableObjectPropertyKey<String> TITLE =
@@ -29,7 +29,7 @@
     /* package */ static final WritableIntPropertyKey SECURITY_ICON = new WritableIntPropertyKey();
 
     /* package */ static final PropertyKey[] ALL_KEYS =
-            new PropertyKey[] {ORIGIN, TITLE, LOAD_PROGRESS, PROGRESS_VISIBLE, SECURITY_ICON};
+            new PropertyKey[] {URL, TITLE, LOAD_PROGRESS, PROGRESS_VISIBLE, SECURITY_ICON};
 
     // Prevent instantiation.
     private PaymentHandlerToolbarProperties() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarViewBinder.java
index 263802f..def3f53b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarViewBinder.java
@@ -6,6 +6,7 @@
 
 import android.view.View;
 
+import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -16,8 +17,10 @@
 /* package */ class PaymentHandlerToolbarViewBinder {
     /* package */ static void bind(
             PropertyModel model, PaymentHandlerToolbarView view, PropertyKey propertyKey) {
-        if (PaymentHandlerToolbarProperties.ORIGIN == propertyKey) {
-            view.mOriginView.setText(model.get(PaymentHandlerToolbarProperties.ORIGIN).toString());
+        if (PaymentHandlerToolbarProperties.URL == propertyKey) {
+            String origin = UrlFormatter.formatUrlForSecurityDisplayOmitScheme(
+                    model.get(PaymentHandlerToolbarProperties.URL).toString());
+            view.mOriginView.setText(origin);
         } else if (PaymentHandlerToolbarProperties.TITLE == propertyKey) {
             view.mTitleView.setText(model.get(PaymentHandlerToolbarProperties.TITLE));
         } else if (PaymentHandlerToolbarProperties.LOAD_PROGRESS == propertyKey) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index e0a47c1b..bc9be11 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -19,7 +19,6 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.signin.SigninManager.SignInCallback;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.components.signin.AccountManagerFacade;
@@ -138,10 +137,8 @@
             return;
         }
 
-        boolean mice_enabled =
-                ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY);
         Account syncAccount = mChromeSigninController.getSignedInUser();
-        if (syncAccount == null && !mice_enabled) {
+        if (syncAccount == null) {
             return;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
index 2d33a5f4..6136982 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
@@ -16,14 +16,10 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
-import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
 import org.chromium.chrome.browser.settings.ManagedPreferencesUtils;
 import org.chromium.chrome.browser.settings.sync.AccountManagementFragment;
 import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.GAIAServiceType;
-import org.chromium.components.signin.SigninActivityMonitor;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -38,7 +34,6 @@
 
     /**
      * Opens a Settings page to configure settings for a single account.
-     * Note: on Android O+, this method is identical to {@link #openSettingsForAllAccounts}.
      * @param context Context to use when starting the Activity.
      * @param account The account for which the Settings page should be opened.
      * @return Whether or not Android accepted the Intent.
@@ -54,7 +49,6 @@
         return IntentUtils.safeStartActivity(context, intent);
     }
 
-    // TODO(https://crbug.com/955501): Migrate all clients to WindowAndroid and remove this.
     /**
      * Opens a Settings page with all accounts on the device.
      * @param context Context to use when starting the Activity.
@@ -66,91 +60,14 @@
         return IntentUtils.safeStartActivity(context, intent);
     }
 
-    /**
-     * Opens a Settings page with all accounts on the device.
-     * @param windowAndroid WindowAndroid to use when starting the Activity.
-     * @return Whether or not Android accepted the Intent.
-     */
-    public static boolean openSettingsForAllAccounts(WindowAndroid windowAndroid) {
-        Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
-        return startActivity(windowAndroid, intent);
-    }
-
     @CalledByNative
     private static void openAccountManagementScreen(WindowAndroid windowAndroid,
             @GAIAServiceType int gaiaServiceType, @Nullable String email) {
         ThreadUtils.assertOnUiThread();
-
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) {
-            // If Mice is enabled, directly use the system account management flows.
-            switch (gaiaServiceType) {
-                case GAIAServiceType.GAIA_SERVICE_TYPE_SIGNUP:
-                case GAIAServiceType.GAIA_SERVICE_TYPE_ADDSESSION:
-                    AccountManagerFacade accountManagerFacade = AccountManagerFacade.get();
-                    @Nullable
-                    Account account =
-                            email == null ? null : accountManagerFacade.getAccountFromName(email);
-                    if (account == null) {
-                        // Empty or unknown account: add a new account.
-                        // TODO(bsazonov): if email is not empty, pre-fill the account name.
-                        startAddAccountActivity(windowAndroid, gaiaServiceType);
-                    } else {
-                        // Existing account indicates authentication error. Fix it.
-                        accountManagerFacade.updateCredentials(
-                                account, windowAndroid.getActivity().get(), null);
-                    }
-                    break;
-                default:
-                    // Open generic accounts settings.
-                    openSettingsForAllAccounts(windowAndroid);
-                    break;
-            }
-            return;
-        }
-
-        // If Mice is not enabled, open Chrome's account management screen.
         AccountManagementFragment.openAccountManagementScreen(gaiaServiceType);
     }
 
     /**
-     * Tries starting an Activity to add a Google account to the device. If this activity cannot
-     * be started, opens "Accounts" page in the Android Settings app.
-     */
-    private static void startAddAccountActivity(
-            WindowAndroid windowAndroid, @GAIAServiceType int gaiaServiceTypeSignup) {
-        logEvent(ProfileAccountManagementMetrics.DIRECT_ADD_ACCOUNT, gaiaServiceTypeSignup);
-
-        AccountManagerFacade.get().createAddAccountIntent((@Nullable Intent intent) -> {
-            if (intent != null && startActivity(windowAndroid, intent)) {
-                return;
-            }
-            // Failed to create or show an intent, open settings for all accounts so
-            // the user has a chance to create an account manually.
-            SigninUtils.openSettingsForAllAccounts(windowAndroid);
-        });
-    }
-
-    // TODO(https://crbug.com/953765): Move this to SigninActivityMonitor.
-    /**
-     * Starts an activity using the provided intent. The started activity will be tracked by
-     * {@link SigninActivityMonitor#hasOngoingActivity()}.
-     *
-     * @param windowAndroid The window to use when launching the intent.
-     * @param intent The intent to launch.
-     * @return Whether {@link WindowAndroid#showIntent} succeeded.
-     */
-    private static boolean startActivity(WindowAndroid windowAndroid, Intent intent) {
-        SigninActivityMonitor signinActivityMonitor = SigninActivityMonitor.get();
-        WindowAndroid.IntentCallback intentCallback =
-                (window, resultCode, data) -> signinActivityMonitor.activityFinished();
-        if (windowAndroid.showIntent(intent, intentCallback, null)) {
-            signinActivityMonitor.activityStarted();
-            return true;
-        }
-        return false;
-    }
-
-    /**
      * Launches the {@link SigninActivity} if signin is allowed.
      * @param accessPoint {@link SigninAccessPoint} for starting sign-in flow.
      * @return a boolean indicating if the SigninActivity is launched.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
index eb6cc739..2258092 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
@@ -12,8 +12,8 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java
index cc634e39..84e2257 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java
@@ -36,7 +36,7 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
 import org.chromium.chrome.browser.ntp.cards.ScrollToLoadListener;
 import org.chromium.chrome.browser.ui.widget.animation.Interpolators;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSection.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSection.java
index 99cd1c3..4cb1c2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSection.java
@@ -20,7 +20,7 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 
 /**
  * The model and controller for a group of site suggestions.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java
new file mode 100644
index 0000000..2efb2aef
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java
@@ -0,0 +1,122 @@
+// 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.toolbar.top;
+
+import android.view.View;
+import android.view.ViewStub;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
+import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+
+/**
+ * The controller for the StartSurfaceToolbar. This class handles all interactions that the
+ * StartSurfaceToolbar has with the outside world. Lazily creates the tab toolbar the first time
+ * it's needed.
+ */
+class StartSurfaceToolbarCoordinator {
+    private final StartSurfaceToolbarMediator mToolbarMediator;
+    private final ViewStub mStub;
+    private final PropertyModel mPropertyModel;
+    private StartSurfaceToolbarView mView;
+    private TabModelSelector mTabModelSelector;
+    private IncognitoSwitchCoordinator mIncognitoSwitchCoordinator;
+
+    StartSurfaceToolbarCoordinator(ViewStub startSurfaceToolbarStub) {
+        mStub = startSurfaceToolbarStub;
+        mPropertyModel = new PropertyModel(StartSurfaceToolbarProperties.ALL_KEYS);
+        mToolbarMediator = new StartSurfaceToolbarMediator(mPropertyModel);
+    }
+
+    /**
+     * Cleans up any code and removes observers as necessary.
+     */
+    void destroy() {
+        mToolbarMediator.destroy();
+    }
+    /**
+     * @param appMenuButtonHelper The helper for managing menu button interactions.
+     */
+    void setAppMenuButtonHelper(AppMenuButtonHelper appMenuButtonHelper) {
+        mToolbarMediator.setAppMenuButtonHelper(appMenuButtonHelper);
+    }
+
+    /**
+     * Sets the OnClickListener that will be notified when the New Tab button is pressed.
+     * @param listener The callback that will be notified when the New Tab button is pressed.
+     */
+    void setOnNewTabClickHandler(View.OnClickListener listener) {
+        mToolbarMediator.setOnNewTabClickHandler(listener);
+    }
+
+    /**
+     * Sets the current {@Link TabModelSelector} so the toolbar can pass it into buttons that need
+     * access to it.
+     */
+    void setTabModelSelector(TabModelSelector selector) {
+        mTabModelSelector = selector;
+        mToolbarMediator.setTabModelSelector(selector);
+    }
+    /**
+     * Called when Start Surface mode is entered or exited.
+     * @param inStartSurfaceMode Whether or not start surface mode should be shown or hidden.
+     */
+    void setStartSurfaceMode(boolean inStartSurfaceMode) {
+        if (!isInflated()) {
+            inflate();
+        }
+        mToolbarMediator.setStartSurfaceMode(inStartSurfaceMode);
+    }
+
+    /**
+     * @param provider The provider used to determine incognito state.
+     */
+    void setIncognitoStateProvider(IncognitoStateProvider provider) {
+        mToolbarMediator.setIncognitoStateProvider(provider);
+    }
+
+    /**
+     * Called to set the visibility in Start Surface mode.
+     * @param shouldShowStartSurfaceToolbar whether the toolbar should be visible.
+     */
+    void setStartSurfaceToolbarVisibility(boolean shouldShowStartSurfaceToolbar) {
+        mToolbarMediator.setStartSurfaceToolbarVisibility(shouldShowStartSurfaceToolbar);
+    }
+
+    /**
+     * Called when accessibility status changes.
+     * @param enabled whether accessibility status is enabled.
+     */
+    void onAccessibilityStatusChanged(boolean enabled) {
+        mToolbarMediator.onAccessibilityStatusChanged(enabled);
+    }
+
+    /**
+     * @param isVisible Whether the bottom toolbar is visible.
+     */
+    void onBottomToolbarVisibilityChanged(boolean isVisible) {
+        mToolbarMediator.onBottomToolbarVisibilityChanged(isVisible);
+    }
+
+    void onNativeLibraryReady() {
+        mToolbarMediator.onNativeLibraryReady();
+    }
+
+    private void inflate() {
+        mStub.setLayoutResource(R.layout.start_top_toolbar);
+        mView = (StartSurfaceToolbarView) mStub.inflate();
+        PropertyModelChangeProcessor.create(
+                mPropertyModel, mView, StartSurfaceToolbarViewBinder::bind);
+
+        mIncognitoSwitchCoordinator = new IncognitoSwitchCoordinator(mView, mTabModelSelector);
+    }
+
+    private boolean isInflated() {
+        return mView != null;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
new file mode 100644
index 0000000..f85e364
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
@@ -0,0 +1,115 @@
+// 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.toolbar.top;
+
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.ACCESSIBILITY_ENABLED;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.APP_MENU_BUTTON_HELPER;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_STATE_PROVIDER;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.LOGO_IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.MENU_IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.NEW_TAB_CLICK_HANDLER;
+
+import android.view.View;
+
+import org.chromium.chrome.browser.flags.FeatureUtilities;
+import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
+import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
+import org.chromium.components.search_engines.TemplateUrlService.TemplateUrlServiceObserver;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/** The mediator implements interacts between the views and the caller. */
+class StartSurfaceToolbarMediator {
+    private final PropertyModel mPropertyModel;
+    private TabModelSelector mTabModelSelector;
+    private TemplateUrlServiceObserver mTemplateUrlObserver;
+    private TabModelSelectorObserver mTabModelSelectorObserver;
+
+    StartSurfaceToolbarMediator(PropertyModel model) {
+        mPropertyModel = model;
+        mPropertyModel.set(MENU_IS_VISIBLE, !FeatureUtilities.isBottomToolbarEnabled());
+
+        // Observers
+
+        mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
+            @Override
+            public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
+                mPropertyModel.set(IS_INCOGNITO, mTabModelSelector.isIncognitoSelected());
+            }
+        };
+    }
+
+    void onNativeLibraryReady() {
+        if (mTemplateUrlObserver != null) {
+            mTemplateUrlObserver = new TemplateUrlServiceObserver() {
+                @Override
+                public void onTemplateURLServiceChanged() {
+                    mPropertyModel.set(LOGO_IS_VISIBLE,
+                            TemplateUrlServiceFactory.get().isDefaultSearchEngineGoogle());
+                }
+            };
+        }
+        TemplateUrlServiceFactory.get().addObserver(mTemplateUrlObserver);
+        mPropertyModel.set(
+                LOGO_IS_VISIBLE, TemplateUrlServiceFactory.get().isDefaultSearchEngineGoogle());
+    }
+
+    void destroy() {
+        if (mTemplateUrlObserver != null) {
+            TemplateUrlServiceFactory.get().removeObserver(mTemplateUrlObserver);
+        }
+        if (mTabModelSelectorObserver != null) {
+            mTabModelSelector.removeObserver(mTabModelSelectorObserver);
+        }
+    }
+
+    void setAppMenuButtonHelper(AppMenuButtonHelper appMenuButtonHelper) {
+        mPropertyModel.set(APP_MENU_BUTTON_HELPER, appMenuButtonHelper);
+    }
+
+    void setOnNewTabClickHandler(View.OnClickListener listener) {
+        mPropertyModel.set(NEW_TAB_CLICK_HANDLER, listener);
+    }
+
+    void setTabModelSelector(TabModelSelector selector) {
+        mTabModelSelector = selector;
+
+        if (mTabModelSelector != null) {
+            mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
+                @Override
+                public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
+                    mPropertyModel.set(IS_INCOGNITO, mTabModelSelector.isIncognitoSelected());
+                }
+            };
+        }
+        mTabModelSelector.addObserver(mTabModelSelectorObserver);
+    }
+
+    void setStartSurfaceMode(boolean inStartSurfaceMode) {
+        mPropertyModel.set(IS_VISIBLE, inStartSurfaceMode);
+    }
+
+    void setIncognitoStateProvider(IncognitoStateProvider provider) {
+        mPropertyModel.set(INCOGNITO_STATE_PROVIDER, provider);
+    }
+
+    void setStartSurfaceToolbarVisibility(boolean shouldShowStartSurfaceToolbar) {
+        mPropertyModel.set(IS_VISIBLE, shouldShowStartSurfaceToolbar);
+    }
+
+    void onAccessibilityStatusChanged(boolean enabled) {
+        mPropertyModel.set(ACCESSIBILITY_ENABLED, enabled);
+    }
+
+    void onBottomToolbarVisibilityChanged(boolean isVisible) {
+        mPropertyModel.set(MENU_IS_VISIBLE, !isVisible);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java
new file mode 100644
index 0000000..1ae0472
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java
@@ -0,0 +1,41 @@
+// 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.toolbar.top;
+
+import android.view.View;
+
+import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
+import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/** List of the start surface toolbar properties. */
+class StartSurfaceToolbarProperties {
+    private StartSurfaceToolbarProperties() {}
+
+    public static final PropertyModel
+            .WritableObjectPropertyKey<AppMenuButtonHelper> APP_MENU_BUTTON_HELPER =
+            new PropertyModel.WritableObjectPropertyKey<AppMenuButtonHelper>();
+    public static final PropertyModel
+            .WritableObjectPropertyKey<IncognitoStateProvider> INCOGNITO_STATE_PROVIDER =
+            new PropertyModel.WritableObjectPropertyKey<IncognitoStateProvider>();
+    public static final PropertyModel
+            .WritableObjectPropertyKey<View.OnClickListener> NEW_TAB_CLICK_HANDLER =
+            new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>();
+    public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
+            new PropertyModel.WritableBooleanPropertyKey();
+    public static final PropertyModel.WritableBooleanPropertyKey LOGO_IS_VISIBLE =
+            new PropertyModel.WritableBooleanPropertyKey();
+    public static final PropertyModel.WritableBooleanPropertyKey IS_INCOGNITO =
+            new PropertyModel.WritableBooleanPropertyKey();
+    public static final PropertyModel.WritableBooleanPropertyKey ACCESSIBILITY_ENABLED =
+            new PropertyModel.WritableBooleanPropertyKey();
+    public static final PropertyModel.WritableBooleanPropertyKey MENU_IS_VISIBLE =
+            new PropertyModel.WritableBooleanPropertyKey();
+
+    public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {APP_MENU_BUTTON_HELPER,
+            NEW_TAB_CLICK_HANDLER, IS_VISIBLE, LOGO_IS_VISIBLE, IS_INCOGNITO,
+            INCOGNITO_STATE_PROVIDER, ACCESSIBILITY_ENABLED, MENU_IS_VISIBLE};
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
new file mode 100644
index 0000000..3e2ecf4
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
@@ -0,0 +1,112 @@
+// 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.toolbar.top;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.support.v7.content.res.AppCompatResources;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
+import org.chromium.chrome.browser.toolbar.MenuButton;
+import org.chromium.chrome.browser.toolbar.NewTabButton;
+import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
+import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.components.browser_ui.styles.ChromeColors;
+
+/** View of the StartSurfaceToolbar */
+class StartSurfaceToolbarView extends RelativeLayout {
+    private NewTabButton mNewTabButton;
+    private View mIncognitoSwitch;
+    private MenuButton mMenuButton;
+    private View mLogo;
+    private int mPrimaryColor;
+    private ColorStateList mLightIconTint;
+    private ColorStateList mDarkIconTint;
+
+    public StartSurfaceToolbarView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mNewTabButton = findViewById(R.id.new_tab_button);
+        mIncognitoSwitch = findViewById(R.id.incognito_switch);
+        mMenuButton = findViewById(R.id.menu_button_wrapper);
+        mLogo = findViewById(R.id.logo);
+        updatePrimaryColorAndTint(false);
+    }
+
+    /**
+     * @param appMenuButtonHelper The {@link AppMenuButtonHelper} for managing menu button
+     *         interactions.
+     */
+    void setAppMenuButtonHelper(AppMenuButtonHelper appMenuButtonHelper) {
+        mMenuButton.getImageButton().setOnTouchListener(appMenuButtonHelper);
+        mMenuButton.getImageButton().setAccessibilityDelegate(
+                appMenuButtonHelper.getAccessibilityDelegate());
+    }
+
+    /**
+     * Sets the {@link OnClickListener} that will be notified when the New Tab button is pressed.
+     * @param listener The callback that will be notified when the New Tab button is pressed.
+     */
+    void setOnNewTabClickHandler(View.OnClickListener listener) {
+        mNewTabButton.setOnClickListener(listener);
+    }
+
+    /**
+     * @param isVisible Whether the Logo is visible.
+     */
+    void setLogoVisibility(boolean isVisible) {
+        mLogo.setVisibility(isVisible ? View.VISIBLE : View.GONE);
+    }
+
+    /**
+     * @param isVisible Whether the menu button is visible.
+     */
+    void setMenuButtonVisibility(boolean isVisible) {
+        mMenuButton.setVisibility(isVisible ? View.VISIBLE : View.GONE);
+    }
+
+    /** Called when incognito mode changes. */
+    void updateIncognito(boolean isIncognito) {
+        updatePrimaryColorAndTint(isIncognito);
+    }
+
+    /**
+     * @param provider The {@link IncognitoStateProvider} passed to buttons that need access to it.
+     */
+    void setIncognitoStateProvider(IncognitoStateProvider provider) {
+        mNewTabButton.setIncognitoStateProvider(provider);
+    }
+
+    /** Called when accessibility status changes. */
+    void onAccessibilityStatusChanged(boolean enabled) {
+        mNewTabButton.onAccessibilityStatusChanged();
+    }
+
+    private void updatePrimaryColorAndTint(boolean isIncognito) {
+        int primaryColor = ChromeColors.getPrimaryBackgroundColor(getResources(), isIncognito);
+        setBackgroundColor(primaryColor);
+
+        if (mLightIconTint == null) {
+            mLightIconTint =
+                    AppCompatResources.getColorStateList(getContext(), R.color.tint_on_dark_bg);
+            mDarkIconTint =
+                    AppCompatResources.getColorStateList(getContext(), R.color.standard_mode_tint);
+        }
+
+        boolean useLightIcons = ColorUtils.shouldUseLightForegroundOnBackground(primaryColor);
+        ColorStateList tintList = useLightIcons ? mLightIconTint : mDarkIconTint;
+        ApiCompatibilityUtils.setImageTintList(mMenuButton.getImageButton(), tintList);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java
new file mode 100644
index 0000000..935e598
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java
@@ -0,0 +1,43 @@
+// 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.toolbar.top;
+
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.ACCESSIBILITY_ENABLED;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.APP_MENU_BUTTON_HELPER;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_STATE_PROVIDER;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.LOGO_IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.MENU_IS_VISIBLE;
+import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.NEW_TAB_CLICK_HANDLER;
+
+import android.view.View;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+
+// The view binder of the tasks surface view.
+class StartSurfaceToolbarViewBinder {
+    public static void bind(
+            PropertyModel model, StartSurfaceToolbarView view, PropertyKey propertyKey) {
+        if (propertyKey == APP_MENU_BUTTON_HELPER) {
+            view.setAppMenuButtonHelper(model.get(APP_MENU_BUTTON_HELPER));
+        } else if (propertyKey == NEW_TAB_CLICK_HANDLER) {
+            view.setOnNewTabClickHandler(model.get(NEW_TAB_CLICK_HANDLER));
+        } else if (propertyKey == IS_VISIBLE) {
+            view.setVisibility(model.get(IS_VISIBLE) ? View.VISIBLE : View.GONE);
+        } else if (propertyKey == LOGO_IS_VISIBLE) {
+            view.setLogoVisibility(model.get(LOGO_IS_VISIBLE));
+        } else if (propertyKey == IS_INCOGNITO) {
+            view.updateIncognito(model.get(IS_INCOGNITO));
+        } else if (propertyKey == INCOGNITO_STATE_PROVIDER) {
+            view.setIncognitoStateProvider(model.get(INCOGNITO_STATE_PROVIDER));
+        } else if (propertyKey == ACCESSIBILITY_ENABLED) {
+            view.onAccessibilityStatusChanged(model.get(ACCESSIBILITY_ENABLED));
+        } else if (propertyKey == MENU_IS_VISIBLE) {
+            view.setMenuButtonVisibility(model.get(MENU_IS_VISIBLE));
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
index b6dd714..804f372 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.findinpage.FindToolbar;
+import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -57,6 +58,11 @@
      * after ToolbarLayout is inflated.
      */
     private @Nullable TabSwitcherModeTTCoordinatorPhone mTabSwitcherModeCoordinatorPhone;
+    /**
+     * The coordinator for the start surface mode toolbar (phones only) if the StartSurface is
+     * enabled. This will be lazily created after ToolbarLayout is inflated.
+     */
+    private @Nullable StartSurfaceToolbarCoordinator mStartSurfaceToolbarCoordinator;
 
     private HomepageManager.HomepageStateListener mHomepageStateListener =
             new HomepageManager.HomepageStateListener() {
@@ -75,8 +81,15 @@
             ToolbarControlContainer controlContainer, ToolbarLayout toolbarLayout) {
         mToolbarLayout = toolbarLayout;
         if (mToolbarLayout instanceof ToolbarPhone) {
-            mTabSwitcherModeCoordinatorPhone = new TabSwitcherModeTTCoordinatorPhone(
-                    controlContainer.getRootView().findViewById(R.id.tab_switcher_toolbar_stub));
+            if (FeatureUtilities.isStartSurfaceEnabled()) {
+                mStartSurfaceToolbarCoordinator = new StartSurfaceToolbarCoordinator(
+                        controlContainer.getRootView().findViewById(
+                                R.id.tab_switcher_toolbar_stub));
+            } else {
+                mTabSwitcherModeCoordinatorPhone = new TabSwitcherModeTTCoordinatorPhone(
+                        controlContainer.getRootView().findViewById(
+                                R.id.tab_switcher_toolbar_stub));
+            }
         }
         controlContainer.setToolbar(this);
         HomepageManager.getInstance().addListener(mHomepageStateListener);
@@ -99,6 +112,8 @@
         mToolbarLayout.setAppMenuButtonHelper(appMenuButtonHelper);
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.setAppMenuButtonHelper(appMenuButtonHelper);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.setAppMenuButtonHelper(appMenuButtonHelper);
         }
     }
 
@@ -126,6 +141,10 @@
             mTabSwitcherModeCoordinatorPhone.setOnTabSwitcherClickHandler(tabSwitcherClickHandler);
             mTabSwitcherModeCoordinatorPhone.setOnNewTabClickHandler(newTabClickHandler);
             mTabSwitcherModeCoordinatorPhone.setTabModelSelector(tabModelSelector);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.setOnNewTabClickHandler(newTabClickHandler);
+            mStartSurfaceToolbarCoordinator.setTabModelSelector(tabModelSelector);
+            mStartSurfaceToolbarCoordinator.onNativeLibraryReady();
         }
 
         mToolbarLayout.setTabModelSelector(tabModelSelector);
@@ -170,6 +189,8 @@
         mToolbarLayout.destroy();
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.destroy();
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.destroy();
         }
     }
 
@@ -211,13 +232,12 @@
 
     @Override
     public void updateTabSwitcherToolbarState(boolean requestToShow) {
-        if (mTabSwitcherModeCoordinatorPhone == null
+        if (mStartSurfaceToolbarCoordinator == null
                 || mToolbarLayout.getToolbarDataProvider() == null
                 || !mToolbarLayout.getToolbarDataProvider().isInOverviewAndShowingOmnibox()) {
             return;
         }
-
-        mTabSwitcherModeCoordinatorPhone.setTabSwitcherToolbarVisibility(requestToShow);
+        mStartSurfaceToolbarCoordinator.setStartSurfaceToolbarVisibility(requestToShow);
     }
 
     @Override
@@ -311,6 +331,8 @@
         mToolbarLayout.onAccessibilityStatusChanged(enabled);
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.onAccessibilityStatusChanged(enabled);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.onAccessibilityStatusChanged(enabled);
         }
     }
 
@@ -421,6 +443,8 @@
         mToolbarLayout.setTabSwitcherMode(inTabSwitcherMode, showToolbar, delayAnimation);
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.setTabSwitcherMode(inTabSwitcherMode);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.setStartSurfaceMode(inTabSwitcherMode);
         }
     }
 
@@ -449,6 +473,8 @@
     public void setIncognitoStateProvider(IncognitoStateProvider provider) {
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.setIncognitoStateProvider(provider);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.setIncognitoStateProvider(provider);
         }
     }
 
@@ -606,6 +632,8 @@
         mToolbarLayout.onBottomToolbarVisibilityChanged(isVisible);
         if (mTabSwitcherModeCoordinatorPhone != null) {
             mTabSwitcherModeCoordinatorPhone.onBottomToolbarVisibilityChanged(isVisible);
+        } else if (mStartSurfaceToolbarCoordinator != null) {
+            mStartSurfaceToolbarCoordinator.onBottomToolbarVisibilityChanged(isVisible);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
index a92eca8f..c4c3a62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
@@ -31,11 +31,11 @@
 import org.chromium.chrome.browser.ui.widget.FadingShadow;
 import org.chromium.chrome.browser.ui.widget.FadingShadowView;
 import org.chromium.chrome.browser.ui.widget.LoadingView;
-import org.chromium.chrome.browser.ui.widget.displaystyle.DisplayStyleObserver;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig.DisplayStyle;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
+import org.chromium.components.browser_ui.widget.displaystyle.DisplayStyleObserver;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig.DisplayStyle;
 
 import java.util.List;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
index 69844033..aa2c637 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -41,14 +41,14 @@
 import org.chromium.chrome.browser.toolbar.top.ActionModeController;
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
 import org.chromium.chrome.browser.ui.widget.TintedDrawable;
-import org.chromium.chrome.browser.ui.widget.displaystyle.DisplayStyleObserver;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.vr.VrModeObserver;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.widget.NumberRollView;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
+import org.chromium.components.browser_ui.widget.displaystyle.DisplayStyleObserver;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.UiUtils;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
index 325141f..38309fdd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -59,9 +59,6 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
 import org.chromium.chrome.browser.suggestions.ThumbnailGradient;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.ui.widget.displaystyle.VerticalDisplayStyle;
 import org.chromium.chrome.browser.widget.ThumbnailProvider;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
@@ -70,6 +67,9 @@
 import org.chromium.chrome.test.util.browser.suggestions.DummySuggestionsEventReporter;
 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.VerticalDisplayStyle;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
index b3d9c106..dfbfd5a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
@@ -52,7 +52,6 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
@@ -64,6 +63,7 @@
 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
 import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsUnitTestUtils.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsUnitTestUtils.java
index edda909..f21fc5f 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsUnitTestUtils.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsUnitTestUtils.java
@@ -11,9 +11,9 @@
 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
 import org.chromium.chrome.browser.ntp.snippets.SectionHeaderViewHolder;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder;
-import org.chromium.chrome.browser.ui.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.ui.widget.displaystyle.VerticalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
+import org.chromium.components.browser_ui.widget.displaystyle.VerticalDisplayStyle;
 
 /**
  * JUnit specific utility classes for testing suggestions code. Other utility code is in
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index e9d8918e..62b8877 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-81.0.4013.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-81.0.4016.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index 141529e..69d2152 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -147,10 +147,83 @@
 
   android_resources(_resources_target_name) {
     custom_package = "org.chromium.webapk.shell_apk"
-    resource_dirs = [ "res" ]
-    generated_resource_dirs = [ _generated_res_background_dir ]
-    generated_resource_files =
-        get_target_outputs(":$_generate_res_background_xml_target_name")
+    sources = [
+      "res/drawable-hdpi/last_resort_runtime_host_logo.png",
+      "res/drawable-hdpi/notification_badge.png",
+      "res/drawable-hdpi/shortcut_1_icon.png",
+      "res/drawable-hdpi/shortcut_2_icon.png",
+      "res/drawable-hdpi/shortcut_3_icon.png",
+      "res/drawable-hdpi/shortcut_4_icon.png",
+      "res/drawable-hdpi/splash_icon.xml",
+      "res/drawable-mdpi/notification_badge.png",
+      "res/drawable-mdpi/shortcut_1_icon.png",
+      "res/drawable-mdpi/shortcut_2_icon.png",
+      "res/drawable-mdpi/shortcut_3_icon.png",
+      "res/drawable-mdpi/shortcut_4_icon.png",
+      "res/drawable-mdpi/splash_icon.xml",
+      "res/drawable-xhdpi/notification_badge.png",
+      "res/drawable-xhdpi/shortcut_1_icon.png",
+      "res/drawable-xhdpi/shortcut_2_icon.png",
+      "res/drawable-xhdpi/shortcut_3_icon.png",
+      "res/drawable-xhdpi/shortcut_4_icon.png",
+      "res/drawable-xhdpi/splash_icon.xml",
+      "res/drawable-xxhdpi/notification_badge.png",
+      "res/drawable-xxhdpi/shortcut_1_icon.png",
+      "res/drawable-xxhdpi/shortcut_2_icon.png",
+      "res/drawable-xxhdpi/shortcut_3_icon.png",
+      "res/drawable-xxhdpi/shortcut_4_icon.png",
+      "res/drawable-xxhdpi/splash_icon.xml",
+      "res/drawable-xxxhdpi/notification_badge.png",
+      "res/drawable-xxxhdpi/shortcut_1_icon.png",
+      "res/drawable-xxxhdpi/shortcut_2_icon.png",
+      "res/drawable-xxxhdpi/shortcut_3_icon.png",
+      "res/drawable-xxxhdpi/shortcut_4_icon.png",
+      "res/drawable-xxxhdpi/splash_icon.xml",
+      "res/layout/choose_host_browser_dialog.xml",
+      "res/layout/host_browser_list_item.xml",
+      "res/mipmap-anydpi-v26/ic_launcher.xml",
+      "res/mipmap-hdpi/app_icon.xml",
+      "res/mipmap-hdpi/ic_launcher.xml",
+      "res/mipmap-hdpi/maskable_app_icon.xml",
+      "res/mipmap-mdpi/app_icon.xml",
+      "res/mipmap-mdpi/ic_launcher.xml",
+      "res/mipmap-mdpi/ic_launcher_background.png",
+      "res/mipmap-mdpi/ic_launcher_foreground.png",
+      "res/mipmap-mdpi/maskable_app_icon.xml",
+      "res/mipmap-nodpi/app_icon_hdpi.png",
+      "res/mipmap-nodpi/app_icon_mdpi.png",
+      "res/mipmap-nodpi/app_icon_xhdpi.png",
+      "res/mipmap-nodpi/app_icon_xxhdpi.png",
+      "res/mipmap-nodpi/app_icon_xxxhdpi.png",
+      "res/mipmap-nodpi/maskable_app_icon_hdpi.png",
+      "res/mipmap-nodpi/maskable_app_icon_mdpi.png",
+      "res/mipmap-nodpi/maskable_app_icon_xhdpi.png",
+      "res/mipmap-nodpi/maskable_app_icon_xxhdpi.png",
+      "res/mipmap-nodpi/maskable_app_icon_xxxhdpi.png",
+      "res/mipmap-nodpi/maskable_splash_icon_xxhdpi.png",
+      "res/mipmap-nodpi/maskable_splash_icon_xxxhdpi.png",
+      "res/mipmap-nodpi/splash_icon_xxhdpi.png",
+      "res/mipmap-nodpi/splash_icon_xxxhdpi.png",
+      "res/mipmap-xhdpi/app_icon.xml",
+      "res/mipmap-xhdpi/ic_launcher.xml",
+      "res/mipmap-xhdpi/maskable_app_icon.xml",
+      "res/mipmap-xxhdpi/app_icon.xml",
+      "res/mipmap-xxhdpi/ic_launcher.xml",
+      "res/mipmap-xxhdpi/maskable_app_icon.xml",
+      "res/mipmap-xxxhdpi/app_icon.xml",
+      "res/mipmap-xxxhdpi/ic_launcher.xml",
+      "res/mipmap-xxxhdpi/maskable_app_icon.xml",
+      "res/values-hdpi/is_splash_icon_maskable_bool.xml",
+      "res/values-mdpi/is_splash_icon_maskable_bool.xml",
+      "res/values-v17/styles.xml",
+      "res/values-xhdpi/is_splash_icon_maskable_bool.xml",
+      "res/values-xxhdpi/is_splash_icon_maskable_bool.xml",
+      "res/values-xxxhdpi/is_splash_icon_maskable_bool.xml",
+      "res/values/colors.xml",
+      "res/values/dimens.xml",
+      "res/xml/shortcuts.xml",
+    ]
+    sources += get_target_outputs(":$_generate_res_background_xml_target_name")
     deps = [
       ":$_generate_res_background_xml_target_name",
       ":webapk_strings_grd",
diff --git a/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn b/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn
index 6dbef58..a4bc1ca4 100644
--- a/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn
@@ -47,7 +47,9 @@
   renaming_sources += [ generate_new_style_manifest_for_upload_output ]
   renaming_destinations += [ "new_style_AndroidManifest.xml" ]
 
-  renaming_sources += [ "${root_out_dir}/resource_zips/chrome/android/webapk/shell_apk/webapk_strings_grd.resources.zip" ]
+  _strings_target = "//chrome/android/webapk/shell_apk:webapk_strings_grd"
+  _target_out_dir = get_label_info(_strings_target, "target_out_dir")
+  renaming_sources += [ "$_target_out_dir/webapk_strings_grd.resources.zip" ]
   renaming_destinations += [ "res/strings.zip" ]
 
   deps = [
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d1dbf29..171ac82 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1705,8 +1705,6 @@
     "speech/speech_recognizer_delegate.h",
     "speech/tts_controller_delegate_impl.cc",
     "speech/tts_controller_delegate_impl.h",
-    "ssl/bad_clock_blocking_page.cc",
-    "ssl/bad_clock_blocking_page.h",
     "ssl/blocked_interception_blocking_page.cc",
     "ssl/blocked_interception_blocking_page.h",
     "ssl/captive_portal_helper.h",
@@ -1944,6 +1942,7 @@
     "//components/nacl/common:buildflags",
     "//components/payments/core",
     "//components/safe_browsing:buildflags",
+    "//components/services/storage/public/mojom",
     "//components/sync",
     "//components/sync_device_info",
     "//content/public/browser",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index a9cfb5b..b7e9e6c07 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -212,6 +212,7 @@
   "+components/services/patch/public",
   "+components/services/pdf_compositor/public",
   "+components/services/quarantine",
+  '+components/services/storage/public',
   "+components/services/unzip",
   "+components/session_manager",
   "+components/sessions/content",
diff --git a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
index 3585026..dc58ca9b 100644
--- a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
@@ -77,9 +77,7 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppsPrivateApiTest);
 };
 
-// TODO(crbug.com/1038602): Fix this flaky test, and enable it again.
-IN_PROC_BROWSER_TEST_F(ArcAppsPrivateApiTest,
-                       DISABLED_GetPackageNameAndLaunchApp) {
+IN_PROC_BROWSER_TEST_F(ArcAppsPrivateApiTest, GetPackageNameAndLaunchApp) {
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(browser()->profile());
   ASSERT_TRUE(prefs);
   CreateAppInstance(prefs);
diff --git a/chrome/browser/background_fetch/background_fetch_browsertest.cc b/chrome/browser/background_fetch/background_fetch_browsertest.cc
index 1eb3d5f..8a7087d 100644
--- a/chrome/browser/background_fetch/background_fetch_browsertest.cc
+++ b/chrome/browser/background_fetch/background_fetch_browsertest.cc
@@ -698,8 +698,16 @@
   ASSERT_TRUE(items[0].is_off_the_record);
 }
 
+// Flaky on Windows 7 (https://crbug.com/1039250)
+#if defined(OS_WIN)
+#define MAYBE_FetchesRunToCompletionAndUpdateTitle_Fetched \
+  DISABLED_FetchesRunToCompletionAndUpdateTitle_Fetched
+#else
+#define MAYBE_FetchesRunToCompletionAndUpdateTitle_Fetched \
+  FetchesRunToCompletionAndUpdateTitle_Fetched
+#endif
 IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest,
-                       FetchesRunToCompletionAndUpdateTitle_Fetched) {
+                       MAYBE_FetchesRunToCompletionAndUpdateTitle_Fetched) {
   ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage(
       "RunFetchTillCompletion()", "backgroundfetchsuccess"));
   EXPECT_EQ(offline_content_provider_observer_->latest_item().state,
@@ -711,8 +719,16 @@
                        "New Fetched Title!", base::CompareCase::SENSITIVE));
 }
 
+// Flaky on Windows 7 (https://crbug.com/1039250)
+#if defined(OS_WIN)
+#define MAYBE_FetchesRunToCompletionAndUpdateTitle_Failed \
+  DISABLED_FetchesRunToCompletionAndUpdateTitle_Failed
+#else
+#define MAYBE_FetchesRunToCompletionAndUpdateTitle_Failed \
+  FetchesRunToCompletionAndUpdateTitle_Failed
+#endif
 IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest,
-                       FetchesRunToCompletionAndUpdateTitle_Failed) {
+                       MAYBE_FetchesRunToCompletionAndUpdateTitle_Failed) {
   ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage(
       "RunFetchTillCompletionWithMissingResource()", "backgroundfetchfail"));
   EXPECT_EQ(offline_content_provider_observer_->latest_item().state,
@@ -794,7 +810,14 @@
       "This origin does not have permission to start a fetch."));
 }
 
-IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest, FetchFromServiceWorker) {
+// Flaky on Windows 7 (https://crbug.com/1039250)
+#if defined(OS_WIN)
+#define MAYBE_FetchFromServiceWorker DISABLED_FetchFromServiceWorker
+#else
+#define MAYBE_FetchFromServiceWorker FetchFromServiceWorker
+#endif
+IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest,
+                       MAYBE_FetchFromServiceWorker) {
   auto* settings_map =
       HostContentSettingsMapFactory::GetForProfile(browser()->profile());
   DCHECK(settings_map);
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
index b776c27..ec019df 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.cc
@@ -10,12 +10,14 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/indexed_db_context.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/storage_usage_info.h"
 #include "url/origin.h"
 
@@ -24,59 +26,57 @@
 using content::StorageUsageInfo;
 
 BrowsingDataIndexedDBHelper::BrowsingDataIndexedDBHelper(
-    IndexedDBContext* indexed_db_context)
-    : indexed_db_context_(indexed_db_context) {
-  DCHECK(indexed_db_context_.get());
+    content::StoragePartition* storage_partition)
+    : storage_partition_(storage_partition) {
+  DCHECK(storage_partition_);
 }
 
-BrowsingDataIndexedDBHelper::~BrowsingDataIndexedDBHelper() {
-}
+BrowsingDataIndexedDBHelper::~BrowsingDataIndexedDBHelper() {}
 
 void BrowsingDataIndexedDBHelper::StartFetching(FetchCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!callback.is_null());
-  indexed_db_context_->IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &BrowsingDataIndexedDBHelper::FetchIndexedDBInfoInIndexedDBThread,
-          this, std::move(callback)));
+  storage_partition_->GetIndexedDBControl().GetUsage(
+      base::BindOnce(&BrowsingDataIndexedDBHelper::IndexedDBUsageInfoReceived,
+                     base::WrapRefCounted(this), std::move(callback)));
 }
 
 void BrowsingDataIndexedDBHelper::DeleteIndexedDB(const GURL& origin) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  indexed_db_context_->IDBTaskRunner()->PostTask(
+  storage_partition_->GetIndexedDBContext()->IDBTaskRunner()->PostTask(
       FROM_HERE,
       base::BindOnce(
-          &BrowsingDataIndexedDBHelper::DeleteIndexedDBInIndexedDBThread, this,
+          &BrowsingDataIndexedDBHelper::DeleteIndexedDBInIndexedDBThread,
+          base::WrapRefCounted(this),
+          base::WrapRefCounted(storage_partition_->GetIndexedDBContext()),
           origin));
 }
 
-void BrowsingDataIndexedDBHelper::FetchIndexedDBInfoInIndexedDBThread(
-    FetchCallback callback) {
-  DCHECK(indexed_db_context_->IDBTaskRunner()->RunsTasksInCurrentSequence());
+void BrowsingDataIndexedDBHelper::IndexedDBUsageInfoReceived(
+    FetchCallback callback,
+    std::vector<storage::mojom::IndexedDBStorageUsageInfoPtr> origins) {
   DCHECK(!callback.is_null());
-  std::vector<StorageUsageInfo> origins =
-      indexed_db_context_->GetAllOriginsInfo();
   std::list<content::StorageUsageInfo> result;
-  for (const StorageUsageInfo& origin : origins) {
-    if (!BrowsingDataHelper::HasWebScheme(origin.origin.GetURL()))
+  for (const auto& origin_usage : origins) {
+    if (!BrowsingDataHelper::HasWebScheme(origin_usage->origin.GetURL()))
       continue;  // Non-websafe state is not considered browsing data.
-    result.push_back(origin);
+    result.push_back(StorageUsageInfo(origin_usage->origin,
+                                      origin_usage->size_in_bytes,
+                                      origin_usage->last_modified_time));
   }
-  base::PostTask(FROM_HERE, {BrowserThread::UI},
-                 base::BindOnce(std::move(callback), result));
+  std::move(callback).Run(std::move(result));
 }
 
 void BrowsingDataIndexedDBHelper::DeleteIndexedDBInIndexedDBThread(
+    scoped_refptr<content::IndexedDBContext> context,
     const GURL& origin) {
-  DCHECK(indexed_db_context_->IDBTaskRunner()->RunsTasksInCurrentSequence());
-  indexed_db_context_->DeleteForOrigin(url::Origin::Create(origin));
+  DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
+  context->DeleteForOrigin(url::Origin::Create(origin));
 }
 
 CannedBrowsingDataIndexedDBHelper::CannedBrowsingDataIndexedDBHelper(
-    content::IndexedDBContext* context)
-    : BrowsingDataIndexedDBHelper(context) {
-}
+    content::StoragePartition* storage_partition)
+    : BrowsingDataIndexedDBHelper(storage_partition) {}
 
 CannedBrowsingDataIndexedDBHelper::~CannedBrowsingDataIndexedDBHelper() {}
 
@@ -116,8 +116,7 @@
                  base::BindOnce(std::move(callback), result));
 }
 
-void CannedBrowsingDataIndexedDBHelper::DeleteIndexedDB(
-    const GURL& origin) {
+void CannedBrowsingDataIndexedDBHelper::DeleteIndexedDB(const GURL& origin) {
   pending_origins_.erase(url::Origin::Create(origin));
   BrowsingDataIndexedDBHelper::DeleteIndexedDB(origin);
 }
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
index d7daeb2..16ec4e1 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper.h
@@ -14,11 +14,13 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom-forward.h"
 #include "content/public/browser/indexed_db_context.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
 namespace content {
+class StoragePartition;
 struct StorageUsageInfo;
 }
 
@@ -35,7 +37,8 @@
 
   // Create a BrowsingDataIndexedDBHelper instance for the indexed databases
   // stored in |context|'s associated profile's user data directory.
-  explicit BrowsingDataIndexedDBHelper(content::IndexedDBContext* context);
+  explicit BrowsingDataIndexedDBHelper(
+      content::StoragePartition* storage_partition);
 
   // Starts the fetching process, which will notify its completion via
   // |callback|. This must be called only on the UI thread.
@@ -46,15 +49,20 @@
  protected:
   virtual ~BrowsingDataIndexedDBHelper();
 
-  scoped_refptr<content::IndexedDBContext> indexed_db_context_;
+  content::StoragePartition* storage_partition_;
 
  private:
   friend class base::RefCountedThreadSafe<BrowsingDataIndexedDBHelper>;
 
   // Enumerates all indexed database files in the IndexedDB thread.
-  void FetchIndexedDBInfoInIndexedDBThread(FetchCallback callback);
+  void IndexedDBUsageInfoReceived(
+      FetchCallback callback,
+      std::vector<storage::mojom::IndexedDBStorageUsageInfoPtr> origins);
+
   // Delete a single indexed database in the IndexedDB thread.
-  void DeleteIndexedDBInIndexedDBThread(const GURL& origin);
+  void DeleteIndexedDBInIndexedDBThread(
+      scoped_refptr<content::IndexedDBContext> context,
+      const GURL& origin);
 
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataIndexedDBHelper);
 };
@@ -66,7 +74,7 @@
     : public BrowsingDataIndexedDBHelper {
  public:
   explicit CannedBrowsingDataIndexedDBHelper(
-      content::IndexedDBContext* context);
+      content::StoragePartition* storage_partition);
 
   // Add a indexed database to the set of canned indexed databases that is
   // returned by this helper.
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_indexed_db_helper_browsertest.cc
index dbbfd03a..8e0b2435 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper_browsertest.cc
@@ -24,9 +24,9 @@
 
 class BrowsingDataIndexedDBHelperTest : public InProcessBrowserTest {
  public:
-  content::IndexedDBContext* IndexedDBContext() {
+  content::StoragePartition* StoragePartition() {
     return content::BrowserContext::GetDefaultStoragePartition(
-        browser()->profile())->GetIndexedDBContext();
+        browser()->profile());
   }
 };
 
@@ -35,14 +35,13 @@
   const GURL origin2("http://host2:1/");
 
   scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(IndexedDBContext()));
+      new CannedBrowsingDataIndexedDBHelper(StoragePartition()));
   helper->Add(url::Origin::Create(origin1));
   helper->Add(url::Origin::Create(origin2));
 
   TestCompletionCallback callback;
-  helper->StartFetching(
-      base::Bind(&TestCompletionCallback::callback,
-                 base::Unretained(&callback)));
+  helper->StartFetching(base::Bind(&TestCompletionCallback::callback,
+                                   base::Unretained(&callback)));
 
   std::list<content::StorageUsageInfo> result = callback.result();
 
@@ -57,14 +56,13 @@
   const GURL origin("http://host1:1/");
 
   scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(IndexedDBContext()));
+      new CannedBrowsingDataIndexedDBHelper(StoragePartition()));
   helper->Add(url::Origin::Create(origin));
   helper->Add(url::Origin::Create(origin));
 
   TestCompletionCallback callback;
-  helper->StartFetching(
-      base::Bind(&TestCompletionCallback::callback,
-                 base::Unretained(&callback)));
+  helper->StartFetching(base::Bind(&TestCompletionCallback::callback,
+                                   base::Unretained(&callback)));
 
   std::list<content::StorageUsageInfo> result = callback.result();
 
diff --git a/chrome/browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc
index 91a9f67..91d1f2d 100644
--- a/chrome/browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc
@@ -4,10 +4,12 @@
 
 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
 
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/indexed_db_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,9 +18,8 @@
 
 class CannedBrowsingDataIndexedDBHelperTest : public testing::Test {
  public:
-  content::IndexedDBContext* IndexedDBContext() {
-    return content::BrowserContext::GetDefaultStoragePartition(&profile_)->
-        GetIndexedDBContext();
+  content::StoragePartition* StoragePartition() {
+    return content::BrowserContext::GetDefaultStoragePartition(&profile_);
   }
 
  private:
@@ -29,7 +30,7 @@
 TEST_F(CannedBrowsingDataIndexedDBHelperTest, Empty) {
   const GURL origin("http://host1:1/");
   scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(IndexedDBContext()));
+      new CannedBrowsingDataIndexedDBHelper(StoragePartition()));
 
   ASSERT_TRUE(helper->empty());
   helper->Add(url::Origin::Create(origin));
@@ -43,7 +44,7 @@
   const GURL origin2("http://example.com");
 
   scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(IndexedDBContext()));
+      new CannedBrowsingDataIndexedDBHelper(StoragePartition()));
 
   EXPECT_TRUE(helper->empty());
   helper->Add(url::Origin::Create(origin1));
@@ -51,6 +52,12 @@
   EXPECT_EQ(2u, helper->GetCount());
   helper->DeleteIndexedDB(origin2);
   EXPECT_EQ(1u, helper->GetCount());
+
+  // TODO(dmurph): Remove this once Delete is mojo-ified as well.
+  base::RunLoop loop;
+  StoragePartition()->GetIndexedDBContext()->IDBTaskRunner()->PostTask(
+      FROM_HERE, loop.QuitClosure());
+  loop.Run();
 }
 
 TEST_F(CannedBrowsingDataIndexedDBHelperTest, IgnoreExtensionsAndDevTools) {
@@ -58,7 +65,7 @@
   const GURL origin2("devtools://abcdefghijklmnopqrstuvwxyz/");
 
   scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(IndexedDBContext()));
+      new CannedBrowsingDataIndexedDBHelper(StoragePartition()));
 
   ASSERT_TRUE(helper->empty());
   helper->Add(url::Origin::Create(origin1));
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index acd76190..8914f3a5 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -521,8 +521,6 @@
     Profile* profile = GetBrowser()->profile();
     content::StoragePartition* storage_partition =
         content::BrowserContext::GetDefaultStoragePartition(profile);
-    content::IndexedDBContext* indexed_db_context =
-        storage_partition->GetIndexedDBContext();
     content::ServiceWorkerContext* service_worker_context =
         storage_partition->GetServiceWorkerContext();
     content::CacheStorageContext* cache_storage_context =
@@ -535,7 +533,7 @@
         new BrowsingDataLocalStorageHelper(profile),
         /*session_storage_helper=*/nullptr,
         new BrowsingDataAppCacheHelper(storage_partition->GetAppCacheService()),
-        new BrowsingDataIndexedDBHelper(indexed_db_context),
+        new BrowsingDataIndexedDBHelper(storage_partition),
         BrowsingDataFileSystemHelper::Create(file_system_context),
         BrowsingDataQuotaHelper::Create(profile),
         new BrowsingDataServiceWorkerHelper(service_worker_context),
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index 756bd4a3..2f76160 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -1962,7 +1962,7 @@
       new BrowsingDataLocalStorageHelper(profile),
       /*session_storage_helper=*/nullptr,
       new BrowsingDataAppCacheHelper(storage_partition->GetAppCacheService()),
-      new BrowsingDataIndexedDBHelper(storage_partition->GetIndexedDBContext()),
+      new BrowsingDataIndexedDBHelper(storage_partition),
       BrowsingDataFileSystemHelper::Create(file_system_context),
       BrowsingDataQuotaHelper::Create(profile),
       new BrowsingDataServiceWorkerHelper(
diff --git a/chrome/browser/browsing_data/mock_browsing_data_indexed_db_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_indexed_db_helper.cc
index d3109413..06c9696 100644
--- a/chrome/browser/browsing_data/mock_browsing_data_indexed_db_helper.cc
+++ b/chrome/browser/browsing_data/mock_browsing_data_indexed_db_helper.cc
@@ -16,9 +16,7 @@
 MockBrowsingDataIndexedDBHelper::MockBrowsingDataIndexedDBHelper(
     Profile* profile)
     : BrowsingDataIndexedDBHelper(
-        content::BrowserContext::GetDefaultStoragePartition(profile)->
-            GetIndexedDBContext()) {
-}
+          content::BrowserContext::GetDefaultStoragePartition(profile)) {}
 
 MockBrowsingDataIndexedDBHelper::~MockBrowsingDataIndexedDBHelper() {
 }
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
index ace831e..ff12fcae 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -69,11 +69,9 @@
   if (!active_window)
     return;
 
-  aura::Window* toplevel_window = active_window->GetToplevelWindow();
-
   gfx::Rect bounds_in_screen = gfx::ScaleToEnclosingRect(
       node_data->bounds_in_screen,
-      1.0f / toplevel_window->layer()->device_scale_factor());
+      1.0f / wm_helper->GetDefaultDeviceScaleFactor());
 
   views::Widget* widget = views::Widget::GetWidgetForNativeView(active_window);
   DCHECK(widget);
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index 0a38b591..079b24d 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h"
 #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
+#include "components/exo/wm_helper.h"
 #include "extensions/browser/api/automation_internal/automation_event_router.h"
 #include "extensions/common/extension_messages.h"
 #include "ui/accessibility/ax_enums.mojom.h"
@@ -230,10 +231,13 @@
     return info_data_bounds;
   }
 
+  exo::WMHelper* wm_helper = exo::WMHelper::GetInstance();
+  if (!wm_helper)
+    return info_data_bounds;
+
   // TODO(katie): offset_container_id should work and we shouldn't have to
   // go into this code path for each node.
   aura::Window* toplevel_window = active_window->GetToplevelWindow();
-  float scale = toplevel_window->layer()->device_scale_factor();
 
   views::Widget* widget = views::Widget::GetWidgetForNativeView(active_window);
   DCHECK(widget);
@@ -242,6 +246,8 @@
   const gfx::Rect bounds =
       widget->widget_delegate()->GetContentsView()->GetBoundsInScreen();
 
+  float scale = wm_helper->GetDefaultDeviceScaleFactor();
+
   // Bounds of root node is relative to its container, i.e. contents view
   // (ShellSurfaceBase).
   info_data_bounds.Offset(
@@ -259,7 +265,9 @@
                                                    ->GetBoundsForClientView()
                                                    .y())));
   }
-  return info_data_bounds;
+  return gfx::ScaleToEnclosingRect(
+      info_data_bounds,
+      toplevel_window->layer()->device_scale_factor() / scale);
 }
 
 void AXTreeSourceArc::InvalidateTree() {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 9b1ebde..44857fd 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -2524,6 +2524,12 @@
       break;
   }
 
+  if (result != CrostiniResult::SUCCESS) {
+    LOG(ERROR) << "Failed to create container. VM: " << signal.vm_name()
+               << " container: " << signal.container_name()
+               << " reason: " << signal.failure_reason();
+  }
+
   InvokeAndErasePendingContainerCallbacks(&create_lxd_container_callbacks_,
                                           signal.vm_name(),
                                           signal.container_name(), result);
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.h b/chrome/browser/chromeos/extensions/wallpaper_api.h
index adfd7f9..44d3ecc 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.h
@@ -10,7 +10,6 @@
 #include "chrome/browser/chromeos/extensions/wallpaper_function_base.h"
 #include "chrome/common/extensions/api/wallpaper.h"
 #include "components/account_id/account_id.h"
-#include "net/url_request/url_request_status.h"
 
 // Implementation of chrome.wallpaper.setWallpaper API.
 // After this API being called, a jpeg encoded wallpaper will be saved to
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index bd2afc2..78420511 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -706,14 +706,8 @@
         TestCase("openFileDialogSelectAllDisabled").WithBrowser(),
         TestCase("openMultiFileDialogSelectAllEnabled").WithBrowser()));
 
-#if defined(NDEBUG)
-#define MAYBE_CopyBetweenWindows CopyBetweenWindows
-#else
-// Flaky on Chrome OS Debug. TODO(crbug.com/1008909).
-#define MAYBE_CopyBetweenWindows DISABLED_CopyBetweenWindows
-#endif
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
-    MAYBE_CopyBetweenWindows, /* copy_between_windows.js */
+    CopyBetweenWindows, /* copy_between_windows.js */
     FilesAppBrowserTest,
     ::testing::Values(TestCase("copyBetweenWindowsLocalToDrive"),
                       TestCase("copyBetweenWindowsLocalToUsb"),
diff --git a/chrome/browser/chromeos/login/signin/auth_sync_observer.cc b/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
index 172503f..0ff1fb4 100644
--- a/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
+++ b/chrome/browser/chromeos/login/signin/auth_sync_observer.cc
@@ -9,7 +9,6 @@
 #include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/chromeos/login/reauth_stats.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
-#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
@@ -89,23 +88,9 @@
     const AccountId& account_id = user->GetAccountId();
     DCHECK(account_id.is_valid());
 
-    user_manager::User::OAuthTokenStatus old_status =
-        user->oauth_token_status();
     user_manager::UserManager::Get()->SaveUserOAuthStatus(
         account_id, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
     RecordReauthReason(account_id, ReauthReason::SYNC_FAILED);
-
-    if (user->GetType() == user_manager::USER_TYPE_SUPERVISED &&
-        old_status != user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
-      // Attempt to restore token from file.
-      ChromeUserManager::Get()
-          ->GetSupervisedUserManager()
-          ->LoadSupervisedUserToken(
-              profile_, base::Bind(&AuthSyncObserver::OnSupervisedTokenLoaded,
-                                   base::Unretained(this)));
-      base::RecordAction(
-          base::UserMetricsAction("ManagedUsers_Chromeos_Sync_Invalidated"));
-    }
   } else if (auth_error.state() == GoogleServiceAuthError::NONE) {
     if (user->oauth_token_status() ==
         user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
@@ -121,9 +106,4 @@
   }
 }
 
-void AuthSyncObserver::OnSupervisedTokenLoaded(const std::string& token) {
-  ChromeUserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
-      profile_, token);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signin/auth_sync_observer.h b/chrome/browser/chromeos/login/signin/auth_sync_observer.h
index 425b49d4c..a4f646b 100644
--- a/chrome/browser/chromeos/login/signin/auth_sync_observer.h
+++ b/chrome/browser/chromeos/login/signin/auth_sync_observer.h
@@ -51,9 +51,6 @@
   // in the Primary / Sync account and not a Secondary Account.
   void HandleAuthError(const GoogleServiceAuthError& auth_error);
 
-  // Called on attempt to restore supervised user token.
-  void OnSupervisedTokenLoaded(const std::string& token);
-
   Profile* const profile_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthSyncObserver);
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_constants.cc b/chrome/browser/chromeos/login/supervised/supervised_user_constants.cc
index bbc6d8f3e..0bb07f3 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_constants.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_constants.cc
@@ -8,8 +8,6 @@
 
 namespace chromeos {
 
-const char kSupervisedUserTokenFilename[] = "token";
-
 const char kCryptohomeSupervisedUserKeyLabel[] = "managed";
 const char kCryptohomeMasterKeyLabel[] = "master";
 const char kLegacyCryptohomeSupervisedUserKeyLabel[] = "default-0";
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_constants.h b/chrome/browser/chromeos/login/supervised/supervised_user_constants.h
index 644a671..469a355 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_constants.h
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_constants.h
@@ -9,8 +9,6 @@
 
 namespace chromeos {
 
-extern const char kSupervisedUserTokenFilename[];
-
 extern const char kCryptohomeSupervisedUserKeyLabel[];
 extern const char kCryptohomeMasterKeyLabel[];
 extern const char kLegacyCryptohomeSupervisedUserKeyLabel[];
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.cc b/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.cc
index 00f5023e..5ffdd94da 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.cc
@@ -66,18 +66,10 @@
   return false;
 }
 
-void SupervisedUserLoginFlow::OnSyncSetupDataLoaded(const std::string& token) {
+void SupervisedUserLoginFlow::CheckPasswordChange() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  ConfigureSync(token);
-}
-
-void SupervisedUserLoginFlow::ConfigureSync(const std::string& token) {
   data_loaded_ = true;
 
-  // TODO(antrim): add error handling (no token loaded).
-  // See also: http://crbug.com/312751
-  ChromeUserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
-      profile_, token);
   SupervisedUserAuthentication* auth =
       ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
 
@@ -249,9 +241,7 @@
 
 void SupervisedUserLoginFlow::LaunchExtraSteps(Profile* profile) {
   profile_ = profile;
-  ChromeUserManager::Get()->GetSupervisedUserManager()->LoadSupervisedUserToken(
-      profile, base::Bind(&SupervisedUserLoginFlow::OnSyncSetupDataLoaded,
-                          weak_factory_.GetWeakPtr()));
+  CheckPasswordChange();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.h b/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.h
index 982cfcb3..b3fd184 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.h
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_login_flow.h
@@ -41,8 +41,7 @@
   void Launch();
   void Finish();
 
-  void OnSyncSetupDataLoaded(const std::string& token);
-  void ConfigureSync(const std::string& token);
+  void CheckPasswordChange();
   void OnPasswordChangeDataLoaded(const base::DictionaryValue* password_data);
   void OnPasswordChangeDataLoadFailed();
   void OnNewKeyAdded(std::unique_ptr<base::DictionaryValue> password_data);
diff --git a/chrome/browser/chromeos/login/users/fake_supervised_user_manager.cc b/chrome/browser/chromeos/login/users/fake_supervised_user_manager.cc
index 2156fde..755aa3cd 100644
--- a/chrome/browser/chromeos/login/users/fake_supervised_user_manager.cc
+++ b/chrome/browser/chromeos/login/users/fake_supervised_user_manager.cc
@@ -63,10 +63,4 @@
   return NULL;
 }
 
-void FakeSupervisedUserManager::LoadSupervisedUserToken(
-    Profile* profile,
-    const LoadTokenCallback& callback) {
-  callback.Run("token");
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/fake_supervised_user_manager.h b/chrome/browser/chromeos/login/users/fake_supervised_user_manager.h
index 5d690f3..52db370 100644
--- a/chrome/browser/chromeos/login/users/fake_supervised_user_manager.h
+++ b/chrome/browser/chromeos/login/users/fake_supervised_user_manager.h
@@ -42,10 +42,6 @@
   void SetPasswordInformation(
       const std::string& user_id,
       const base::DictionaryValue* password_info) override {}
-  void LoadSupervisedUserToken(Profile* profile,
-                               const LoadTokenCallback& callback) override;
-  void ConfigureSyncWithToken(Profile* profile,
-                              const std::string& token) override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FakeSupervisedUserManager);
diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager.h b/chrome/browser/chromeos/login/users/supervised_user_manager.h
index 8d6672ea..43814f3 100644
--- a/chrome/browser/chromeos/login/users/supervised_user_manager.h
+++ b/chrome/browser/chromeos/login/users/supervised_user_manager.h
@@ -44,9 +44,6 @@
 // lookup methods that make sense only for supervised users.
 class SupervisedUserManager {
  public:
-  typedef base::Callback<void(const std::string& /* token */)>
-      LoadTokenCallback;
-
   // Registers user manager preferences.
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
@@ -126,14 +123,6 @@
       const std::string& user_id,
       const base::DictionaryValue* password_info) = 0;
 
-  // Loads a sync oauth token in background, and passes it to callback.
-  virtual void LoadSupervisedUserToken(Profile* profile,
-                                       const LoadTokenCallback& callback) = 0;
-
-  // Configures sync service with oauth token.
-  virtual void ConfigureSyncWithToken(Profile* profile,
-                                      const std::string& token) = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(SupervisedUserManager);
 };
diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc
index d0c2183e..c29dffb2 100644
--- a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc
@@ -7,16 +7,12 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
-#include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
@@ -81,16 +77,6 @@
 // key.
 const char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey";
 
-std::string LoadSyncToken(base::FilePath profile_dir) {
-  std::string token;
-  base::FilePath token_file =
-      profile_dir.Append(chromeos::kSupervisedUserTokenFilename);
-  VLOG(1) << "Loading" << token_file.value();
-  if (!base::ReadFileToString(token_file, &token))
-    return std::string();
-  return token;
-}
-
 }  // namespace
 
 namespace chromeos {
@@ -498,25 +484,4 @@
   return authentication_.get();
 }
 
-void SupervisedUserManagerImpl::LoadSupervisedUserToken(
-    Profile* profile,
-    const LoadTokenCallback& callback) {
-  // TODO(antrim): use profile->GetPath() once we sure it is safe.
-  base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash(
-      ProfileHelper::Get()->GetUserByProfile(profile)->username_hash());
-  PostTaskAndReplyWithResult(
-      base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
-                              base::TaskPriority::BEST_EFFORT,
-                              base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
-          .get(),
-      FROM_HERE, base::Bind(&LoadSyncToken, profile_dir), callback);
-}
-
-void SupervisedUserManagerImpl::ConfigureSyncWithToken(
-    Profile* profile,
-    const std::string& token) {
-  if (!token.empty())
-    SupervisedUserServiceFactory::GetForProfile(profile)->InitSync(token);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h
index 8e45c0f3..e2b0b7b 100644
--- a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h
+++ b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h
@@ -48,10 +48,6 @@
   void SetPasswordInformation(
       const std::string& user_id,
       const base::DictionaryValue* password_info) override;
-  void LoadSupervisedUserToken(Profile* profile,
-                               const LoadTokenCallback& callback) override;
-  void ConfigureSyncWithToken(Profile* profile,
-                              const std::string& token) override;
 
  private:
   friend class ChromeUserManagerImpl;
diff --git a/chrome/browser/component_updater/cros_component_installer_chromeos.cc b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
index 0783ad7..82b3d76 100644
--- a/chrome/browser/component_updater/cros_component_installer_chromeos.cc
+++ b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
@@ -38,9 +38,9 @@
      "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"},
     {"cros-termina", "810.1",
      "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"},
-    {"rtanalytics-light", "15.0",
+    {"rtanalytics-light", "16.0",
      "69f09d33c439c2ab55bbbe24b47ab55cb3f6c0bd1f1ef46eefea3216ec925038"},
-    {"rtanalytics-full", "15.0",
+    {"rtanalytics-full", "16.0",
      "c93c3e1013c52100a20038b405ac854d69fa889f6dc4fa6f188267051e05e444"},
     {"star-cups-driver", "1.1",
      "6d24de30f671da5aee6d463d9e446cafe9ddac672800a9defe86877dcde6c466"},
diff --git a/chrome/browser/content_settings/local_shared_objects_container.cc b/chrome/browser/content_settings/local_shared_objects_container.cc
index 681c6396..5988a53a 100644
--- a/chrome/browser/content_settings/local_shared_objects_container.cc
+++ b/chrome/browser/content_settings/local_shared_objects_container.cc
@@ -51,8 +51,7 @@
           content::BrowserContext::GetDefaultStoragePartition(profile)
               ->GetFileSystemContext())),
       indexed_dbs_(new CannedBrowsingDataIndexedDBHelper(
-          content::BrowserContext::GetDefaultStoragePartition(profile)
-              ->GetIndexedDBContext())),
+          content::BrowserContext::GetDefaultStoragePartition(profile))),
       local_storages_(new CannedBrowsingDataLocalStorageHelper(profile)),
       service_workers_(new CannedBrowsingDataServiceWorkerHelper(
           content::BrowserContext::GetDefaultStoragePartition(profile)
diff --git a/chrome/browser/extensions/activity_log/activity_log_browsertest.cc b/chrome/browser/extensions/activity_log/activity_log_browsertest.cc
deleted file mode 100644
index 814ced93..0000000
--- a/chrome/browser/extensions/activity_log/activity_log_browsertest.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/activity_log/activity_log.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/prerender/prerender_handle.h"
-#include "chrome/browser/prerender/prerender_manager.h"
-#include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-
-namespace extensions {
-
-// Only the prerender tests are in this file. To add tests for activity
-// logging please see:
-//    chrome/test/data/extensions/api_test/activity_log_private/README
-
-class ActivityLogPrerenderTest : public ExtensionApiTest {
- protected:
-  // Make sure the activity log is turned on.
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    ExtensionBrowserTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitch(switches::kEnableExtensionActivityLogging);
-  }
-
-  void SetUpOnMainThread() override {
-    ExtensionApiTest::SetUpOnMainThread();
-    host_resolver()->AddRule("*", "127.0.0.1");
-    prerender::PrerenderManager::SetMode(
-        prerender::PrerenderManager::DEPRECATED_PRERENDER_MODE_ENABLED);
-  }
-
-  static void Prerender_Arguments(
-      const std::string& extension_id,
-      uint16_t port,
-      const base::Closure& quit_when_idle_closure,
-      std::unique_ptr<std::vector<scoped_refptr<Action>>> i) {
-    quit_when_idle_closure.Run();
-
-    ASSERT_TRUE(i->size());
-    scoped_refptr<Action> last = i->front();
-
-    ASSERT_EQ(extension_id, last->extension_id());
-    ASSERT_EQ(Action::ACTION_CONTENT_SCRIPT, last->action_type());
-    ASSERT_EQ("[\"/google_cs.js\"]",
-              ActivityLogPolicy::Util::Serialize(last->args()));
-    ASSERT_EQ(
-        base::StringPrintf("http://www.google.com.bo:%u/title1.html", port),
-        last->SerializePageUrl());
-    ASSERT_EQ(base::StringPrintf("www.google.com.bo:%u/title1.html", port),
-              last->page_title());
-    ASSERT_EQ("{\"prerender\":true}",
-              ActivityLogPolicy::Util::Serialize(last->other()));
-    ASSERT_EQ("", last->api_name());
-    ASSERT_EQ("", last->SerializeArgUrl());
-  }
-};
-
-// https://crbug.com/724553
-#if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
-#define MAYBE_TestScriptInjected DISABLED_TestScriptInjected
-#else
-#define MAYBE_TestScriptInjected TestScriptInjected
-#endif  // defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
-
-IN_PROC_BROWSER_TEST_F(ActivityLogPrerenderTest, MAYBE_TestScriptInjected) {
-  ASSERT_TRUE(StartEmbeddedTestServer());
-  uint16_t port = embedded_test_server()->port();
-
-  // Get the extension (chrome/test/data/extensions/activity_log)
-  const Extension* ext =
-      LoadExtension(test_data_dir_.AppendASCII("activity_log"));
-  ASSERT_TRUE(ext);
-
-  ActivityLog* activity_log = ActivityLog::GetInstance(profile());
-  activity_log->SetWatchdogAppActiveForTesting(true);
-  ASSERT_TRUE(activity_log);
-
-  // Disable rate limiting in PrerenderManager
-  prerender::PrerenderManager* prerender_manager =
-      prerender::PrerenderManagerFactory::GetForBrowserContext(profile());
-  ASSERT_TRUE(prerender_manager);
-  prerender_manager->mutable_config().rate_limit_enabled = false;
-  // Increase prerenderer limits, otherwise this test fails
-  // on Windows XP.
-  prerender_manager->mutable_config().max_bytes = 1000 * 1024 * 1024;
-  prerender_manager->mutable_config().time_to_live =
-      base::TimeDelta::FromMinutes(10);
-  prerender_manager->mutable_config().abandon_time_to_live =
-      base::TimeDelta::FromMinutes(10);
-
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(web_contents);
-
-  content::WindowedNotificationObserver page_observer(
-      content::NOTIFICATION_LOAD_STOP,
-      content::NotificationService::AllSources());
-
-  GURL url(base::StringPrintf("http://www.google.com.bo:%u/title1.html", port));
-
-  const gfx::Size kSize(640, 480);
-  std::unique_ptr<prerender::PrerenderHandle> prerender_handle(
-      prerender_manager->AddPrerenderFromOmnibox(
-          url,
-          web_contents->GetController().GetDefaultSessionStorageNamespace(),
-          kSize));
-
-  page_observer.Wait();
-
-  base::RunLoop run_loop;
-  activity_log->GetFilteredActions(
-      ext->id(), Action::ACTION_ANY, "", "", "", -1,
-      base::BindOnce(ActivityLogPrerenderTest::Prerender_Arguments, ext->id(),
-                     port, run_loop.QuitWhenIdleClosure()));
-
-  // Allow invocation of Prerender_Arguments
-  run_loop.Run();
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 3c32b0f..8a4c933 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -243,7 +243,7 @@
 
   prerender::test_utils::RestorePrerenderMode restore_prerender_mode;
   prerender::PrerenderManager::SetMode(
-      prerender::PrerenderManager::DEPRECATED_PRERENDER_MODE_ENABLED);
+      prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH);
   prerender::PrerenderManager* prerender_manager =
       prerender::PrerenderManagerFactory::GetForBrowserContext(profile());
 
@@ -255,7 +255,7 @@
           kSize));
 
   const std::vector<content::WebContents*> contentses =
-      prerender_manager->GetAllPrerenderingContents();
+      prerender_manager->GetAllNoStatePrefetchingContentsForTesting();
   ASSERT_EQ(1U, contentses.size());
   content::WebContents *contents = contentses[0];
   ASSERT_TRUE(prerender_manager->IsWebContentsPrerendering(contents, NULL));
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index b7caea8..2f46064 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -169,8 +169,8 @@
 void IdentityAPI::OnRefreshTokenUpdatedForAccount(
     const CoreAccountInfo& account_info) {
   // Refresh tokens are sometimes made available in contexts where
-  // AccountTrackerService is not tracking the account in question (one example
-  // is SupervisedUserService::InitSync()). Bail out in these cases.
+  // AccountTrackerService is not tracking the account in question. Bail out in
+  // these cases.
   if (account_info.gaia.empty())
     return;
 
diff --git a/chrome/browser/extensions/blacklist_state_fetcher.cc b/chrome/browser/extensions/blacklist_state_fetcher.cc
index b18968c..54e99857 100644
--- a/chrome/browser/extensions/blacklist_state_fetcher.cc
+++ b/chrome/browser/extensions/blacklist_state_fetcher.cc
@@ -14,7 +14,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "net/base/escape.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_status.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
index 210b68b7..50bfbc7 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -226,9 +226,13 @@
   if (extension->from_bookmark())
     return url;
 
-  // If the URL is part of an extension's web extent, convert it to an
-  // extension URL.
-  return extension->GetResourceURL(url.path());
+  // If the URL is part of an extension's web extent, convert it to the
+  // extension's URL.  Note that we don't need to carry over the |url|'s path,
+  // because the process model only uses the origin of a hosted app's effective
+  // URL.  Note also that we must not return an invalid effective URL here,
+  // since that might lead to incorrect security decisions - see
+  // https://crbug.com/1016954.
+  return extension->url();
 }
 
 // static
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 799ddc0..9a56d53 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1290,6 +1290,15 @@
     std::unique_ptr<const PermissionSet> granted_permissions =
         extension_prefs_->GetGrantedPermissions(extension->id());
     CHECK(granted_permissions.get());
+    // We check the union of both granted permissions and runtime granted
+    // permissions as it is possible for permissions which were withheld during
+    // installation to have never entered the granted set, but to have later
+    // been granted as runtime permissions.
+    std::unique_ptr<const PermissionSet> runtime_granted_permissions =
+        extension_prefs_->GetRuntimeGrantedPermissions(extension->id());
+    std::unique_ptr<const PermissionSet> total_permissions =
+        PermissionSet::CreateUnion(*granted_permissions,
+                                   *runtime_granted_permissions);
 
     // Here, we check if an extension's privileges have increased in a manner
     // that requires the user's approval. This could occur because the browser
@@ -1297,7 +1306,7 @@
     // to a version that requires additional privileges.
     is_privilege_increase =
         PermissionMessageProvider::Get()->IsPrivilegeIncrease(
-            *granted_permissions,
+            *total_permissions,
             extension->permissions_data()->active_permissions(),
             extension->GetType());
 
diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc
index 35981d1f..b5c5b9e 100644
--- a/chrome/browser/extensions/permissions_updater.cc
+++ b/chrome/browser/extensions/permissions_updater.cc
@@ -286,6 +286,10 @@
   // host permissions enabled). They're also added to the active set, which is
   // the permission set stored in preferences representing the extension's
   // currently-desired permission state.
+  // TODO(tjudkins): The reasoning for this doesn't entirely hold true now that
+  // we check both the granted permissions and runtime permissions to detect a
+  // permission increase. We should address this as we continue working on
+  // reducing the different ways we store permissions into a unified concept.
   constexpr int permissions_store_mask =
       kActivePermissions | kGrantedPermissions | kRuntimeGrantedPermissions;
   AddPermissionsImpl(extension, permissions, permissions_store_mask,
diff --git a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
index 84effc0d..d813b06 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
@@ -252,11 +252,6 @@
 
   {
     SCOPED_TRACE("Reload after granting single");
-    // TODO(tjudkins): We shouldn't have to explicitly call to grant
-    // permissions here, but at the moment when withholding host permissions on
-    // installation and then granting a permission, the reload or update detects
-    // that as a privilege increase and disables the extension.
-    service()->GrantPermissionsAndEnableExtension(extension.get());
     extension = reload_extension();
     CheckActiveHostPermissions(*extension, {kHostGoogle}, {});
     CheckWithheldHostPermissions(*extension, {kHostChromium}, {});
@@ -274,11 +269,6 @@
 
   {
     SCOPED_TRACE("Reload after setting to not withhold");
-    // TODO(tjudkins): We shouldn't have to explicitly call to grant
-    // permissions here, but at the moment when withholding host permissions on
-    // installation and then granting a permission, the reload or update detects
-    // that as a privilege increase and disables the extension.
-    service()->GrantPermissionsAndEnableExtension(extension.get());
     extension = reload_extension();
     CheckActiveHostPermissions(*extension, {kHostGoogle, kHostChromium}, {});
     CheckWithheldHostPermissions(*extension, {}, {});
@@ -374,11 +364,6 @@
 
   {
     SCOPED_TRACE("Update after granting single");
-    // TODO(tjudkins): We shouldn't have to explicitly call to grant
-    // permissions here, but at the moment when withholding host permissions on
-    // installation and then granting a permission, the reload or update detects
-    // that as a privilege increase and disables the extension.
-    service()->GrantPermissionsAndEnableExtension(extension.get());
     extension = update_extension("3");
     CheckActiveHostPermissions(*extension, {kHostGoogle}, {});
     CheckWithheldHostPermissions(*extension, {kHostChromium}, {});
@@ -396,11 +381,6 @@
 
   {
     SCOPED_TRACE("Update after setting to not withhold");
-    // TODO(tjudkins): We shouldn't have to explicitly call to grant
-    // permissions here, but at the moment when withholding host permissions on
-    // installation and then granting a permission, the reload or update detects
-    // that as a privilege increase and disables the extension.
-    service()->GrantPermissionsAndEnableExtension(extension.get());
     extension = update_extension("4");
     CheckActiveHostPermissions(*extension, {kHostGoogle, kHostChromium}, {});
     CheckWithheldHostPermissions(*extension, {}, {});
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc
index febe157..2fc8d062 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -102,60 +102,57 @@
 // Hopefully we never need a space in a command argument.
 const char kPerfCommandDelimiter[] = " ";
 
-const char kPerfRecordCyclesCmd[] = "perf record -a -e cycles -c 1000003";
+const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003";
 
-const char kPerfRecordFPCallgraphCmd[] =
-    "perf record -a -e cycles -g -c 4000037";
+const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
 
-const char kPerfRecordLBRCallgraphCmd[] =
+const char kPerfLBRCallgraphCmd[] =
     "perf record -a -e cycles -c 4000037 --call-graph lbr";
 
-const char kPerfRecordLBRCmd[] = "perf record -a -e r20c4 -b -c 200011";
+const char kPerfLBRCmd[] = "perf record -a -e r20c4 -b -c 200011";
 
 // Silvermont, Airmont, Goldmont don't have a branches taken event. Therefore,
 // we sample on the branches retired event.
-const char kPerfRecordLBRCmdAtom[] = "perf record -a -e rc4 -b -c 300001";
+const char kPerfLBRCmdAtom[] = "perf record -a -e rc4 -b -c 300001";
 
 // The following events count misses in the level 1 caches and TLBs.
 
 // Perf doesn't support the generic dTLB-misses event for Goldmont. We define it
 // in terms of raw event number and umask value. Event codes taken from
 // "Intel 64 and IA-32 Architectures Software Developer's Manual, Vol 3".
-const char kPerfRecordInstructionTLBMissesCmdGLM[] =
+const char kPerfInstructionTLBMissesCmdGLM[] =
     "perf record -a -e r0481 -c 2003";
 
-const char kPerfRecordDataTLBMissesCmdGLM[] = "perf record -a -e r13d0 -c 2003";
+const char kPerfDataTLBMissesCmdGLM[] = "perf record -a -e r13d0 -c 2003";
 
 // Use the generic event names for the other microarchitectures.
-const char kPerfRecordInstructionTLBMissesCmd[] =
+const char kPerfInstructionTLBMissesCmd[] =
     "perf record -a -e iTLB-misses -c 2003";
 
-const char kPerfRecordDataTLBMissesCmd[] =
-    "perf record -a -e dTLB-misses -c 2003";
+const char kPerfDataTLBMissesCmd[] = "perf record -a -e dTLB-misses -c 2003";
 
 // TLB miss cycles for IvyBridge, Haswell, Broadwell and SandyBridge.
-const char kPerfRecordITLBMissCyclesCmdIvyBridge[] =
+const char kPerfITLBMissCyclesCmdIvyBridge[] =
     "perf record -a -e itlb_misses.walk_duration -c 2003";
 
-const char kPerfRecordDTLBMissCyclesCmdIvyBridge[] =
+const char kPerfDTLBMissCyclesCmdIvyBridge[] =
     "perf record -a -e dtlb_load_misses.walk_duration -c 2003";
 
 // TLB miss cycles for Skylake and Kabylake.
-const char kPerfRecordITLBMissCyclesCmdSkylake[] =
+const char kPerfITLBMissCyclesCmdSkylake[] =
     "perf record -a -e itlb_misses.walk_pending -c 2003";
 
-const char kPerfRecordDTLBMissCyclesCmdSkylake[] =
+const char kPerfDTLBMissCyclesCmdSkylake[] =
     "perf record -a -e dtlb_load_misses.walk_pending -c 2003";
 
 // TLB miss cycles for Atom, including Silvermont, Airmont and Goldmont.
-const char kPerfRecordITLBMissCyclesCmdAtom[] =
+const char kPerfITLBMissCyclesCmdAtom[] =
     "perf record -a -e page_walks.i_side_cycles -c 2003";
 
-const char kPerfRecordDTLBMissCyclesCmdAtom[] =
+const char kPerfDTLBMissCyclesCmdAtom[] =
     "perf record -a -e page_walks.d_side_cycles -c 2003";
 
-const char kPerfRecordCacheMissesCmd[] =
-    "perf record -a -e cache-misses -c 10007";
+const char kPerfCacheMissesCmd[] = "perf record -a -e cache-misses -c 10007";
 
 const std::vector<RandomSelector::WeightAndValue> GetDefaultCommands_x86_64(
     const CPUIdentity& cpuid) {
@@ -163,69 +160,64 @@
   std::vector<WeightAndValue> cmds;
   DCHECK_EQ(cpuid.arch, "x86_64");
   const std::string cpu_uarch = GetCpuUarch(cpuid);
-  // Haswell and newer big Intel cores support LBR callstack profiling. This
-  // requires kernel support, which was added in kernel 4.4, and it was
-  // backported to kernel 3.18. Prefer LBR callstack profiling where supported
-  // instead of FP callchains, because the former works with binaries compiled
-  // with frame pointers disabled, such as the ARC runtime.
-  const char* callgraph_cmd = kPerfRecordFPCallgraphCmd;
-  if (MicroarchitectureHasLBRCallgraph(cpu_uarch) &&
-      KernelReleaseHasLBRCallgraph(cpuid.release)) {
-    callgraph_cmd = kPerfRecordLBRCallgraphCmd;
+
+  // We use different perf events for iTLB, dTLB and LBR profiling on different
+  // microarchitectures. Customize each command based on the microarchitecture.
+  const char* itlb_misses_cmd = kPerfInstructionTLBMissesCmd;
+  const char* dtlb_misses_cmd = kPerfDataTLBMissesCmd;
+  const char* itlb_miss_cycles_cmd = kPerfITLBMissCyclesCmdIvyBridge;
+  const char* dtlb_miss_cycles_cmd = kPerfDTLBMissCyclesCmdIvyBridge;
+  const char* lbr_cmd = kPerfLBRCmd;
+
+  if (cpu_uarch == "Skylake" || cpu_uarch == "Kabylake") {
+    itlb_miss_cycles_cmd = kPerfITLBMissCyclesCmdSkylake;
+    dtlb_miss_cycles_cmd = kPerfDTLBMissCyclesCmdSkylake;
+  }
+  if (cpu_uarch == "Silvermont" || cpu_uarch == "Airmont" ||
+      cpu_uarch == "Goldmont" || cpu_uarch == "GoldmontPlus") {
+    itlb_miss_cycles_cmd = kPerfITLBMissCyclesCmdAtom;
+    dtlb_miss_cycles_cmd = kPerfDTLBMissCyclesCmdAtom;
+    lbr_cmd = kPerfLBRCmdAtom;
+  }
+  if (cpu_uarch == "Goldmont" || cpu_uarch == "GoldmontPlus") {
+    itlb_misses_cmd = kPerfInstructionTLBMissesCmdGLM;
+    dtlb_misses_cmd = kPerfDataTLBMissesCmdGLM;
   }
 
   if (cpu_uarch == "IvyBridge" || cpu_uarch == "Haswell" ||
-      cpu_uarch == "Broadwell" || cpu_uarch == "SandyBridge") {
-    cmds.push_back(WeightAndValue(40.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-    cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordITLBMissCyclesCmdIvyBridge));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDTLBMissCyclesCmdIvyBridge));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
-    return cmds;
-  }
-  if (cpu_uarch == "Skylake" || cpu_uarch == "Kabylake") {
-    cmds.push_back(WeightAndValue(40.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-    cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordITLBMissCyclesCmdSkylake));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDTLBMissCyclesCmdSkylake));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
-    return cmds;
-  }
-  if (cpu_uarch == "Silvermont" || cpu_uarch == "Airmont") {
-    cmds.push_back(WeightAndValue(40.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-    cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmdAtom));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordITLBMissCyclesCmdAtom));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDTLBMissCyclesCmdAtom));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
-    return cmds;
-  }
-  if (cpu_uarch == "Goldmont" || cpu_uarch == "GoldmontPlus") {
-    cmds.push_back(WeightAndValue(40.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-    cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmdAtom));
-    // Use the Goldmont variants of iTLB and dTLB misses.
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmdGLM));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmdGLM));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordITLBMissCyclesCmdAtom));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDTLBMissCyclesCmdAtom));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
+      cpu_uarch == "Broadwell" || cpu_uarch == "SandyBridge" ||
+      cpu_uarch == "Skylake" || cpu_uarch == "Kabylake" ||
+      cpu_uarch == "Silvermont" || cpu_uarch == "Airmont" ||
+      cpu_uarch == "Goldmont" || cpu_uarch == "GoldmontPlus") {
+    cmds.push_back(WeightAndValue(40.0, kPerfCyclesCmd));
+    // Haswell and newer big Intel cores support LBR callstack profiling. This
+    // requires kernel support, which was added in kernel 4.4, and it was
+    // backported to kernel 3.18. Collect LBR callstack profiling where
+    // supported in addition to FP callchains. The former works with binaries
+    // compiled with frame pointers disabled, but it only captures callchains
+    // after profiling is enabled, so it's likely missing the lower frames of
+    // the callstack.
+    if (MicroarchitectureHasLBRCallgraph(cpu_uarch) &&
+        KernelReleaseHasLBRCallgraph(cpuid.release)) {
+      cmds.push_back(WeightAndValue(10.0, kPerfFPCallgraphCmd));
+      cmds.push_back(WeightAndValue(10.0, kPerfLBRCallgraphCmd));
+    } else {
+      cmds.push_back(WeightAndValue(20.0, kPerfFPCallgraphCmd));
+    }
+    cmds.push_back(WeightAndValue(15.0, lbr_cmd));
+    cmds.push_back(WeightAndValue(5.0, itlb_misses_cmd));
+    cmds.push_back(WeightAndValue(5.0, dtlb_misses_cmd));
+    cmds.push_back(WeightAndValue(5.0, itlb_miss_cycles_cmd));
+    cmds.push_back(WeightAndValue(5.0, dtlb_miss_cycles_cmd));
+    cmds.push_back(WeightAndValue(5.0, kPerfCacheMissesCmd));
     return cmds;
   }
   // Other 64-bit x86
-  cmds.push_back(WeightAndValue(65.0, kPerfRecordCyclesCmd));
-  cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-  cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd));
-  cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd));
-  cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
+  cmds.push_back(WeightAndValue(65.0, kPerfCyclesCmd));
+  cmds.push_back(WeightAndValue(20.0, kPerfFPCallgraphCmd));
+  cmds.push_back(WeightAndValue(5.0, kPerfInstructionTLBMissesCmd));
+  cmds.push_back(WeightAndValue(5.0, kPerfDataTLBMissesCmd));
+  cmds.push_back(WeightAndValue(5.0, kPerfCacheMissesCmd));
   return cmds;
 }
 
@@ -256,13 +248,13 @@
   std::vector<WeightAndValue> cmds;
   if (cpuid.arch == "x86" ||     // 32-bit x86, or...
       cpuid.arch == "armv7l") {  // ARM
-    cmds.push_back(WeightAndValue(80.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, kPerfRecordFPCallgraphCmd));
+    cmds.push_back(WeightAndValue(80.0, kPerfCyclesCmd));
+    cmds.push_back(WeightAndValue(20.0, kPerfFPCallgraphCmd));
     return cmds;
   }
 
   // Unknown CPUs
-  cmds.push_back(WeightAndValue(1.0, kPerfRecordCyclesCmd));
+  cmds.push_back(WeightAndValue(1.0, kPerfCyclesCmd));
   return cmds;
 }
 
diff --git a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
index 92bce4a..7e1323b 100644
--- a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
@@ -28,19 +28,21 @@
 
 namespace {
 
-const char kPerfRecordCyclesCmd[] = "perf record -a -e cycles -c 1000003";
-const char kPerfRecordCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
-const char kPerfRecordLBRCmd[] = "perf record -a -e r20c4 -b -c 200011";
-const char kPerfRecordLBRCmdAtom[] = "perf record -a -e rc4 -b -c 300001";
-const char kPerfRecordDataTLBMissesCmdGLM[] = "perf record -a -e r13d0 -c 2003";
-const char kPerfRecordDataTLBMissesCmd[] =
-    "perf record -a -e dTLB-misses -c 2003";
-const char kPerfRecordITLBMissCyclesCmdIvyBridge[] =
+const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003";
+const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
+const char kPerfLBRCallgraphCmd[] =
+    "perf record -a -e cycles -c 4000037 --call-graph lbr";
+const char kPerfLBRCmd[] = "perf record -a -e r20c4 -b -c 200011";
+const char kPerfLBRCmdAtom[] = "perf record -a -e rc4 -b -c 300001";
+const char kPerfDataTLBMissesCmdGLM[] = "perf record -a -e r13d0 -c 2003";
+const char kPerfDataTLBMissesCmd[] = "perf record -a -e dTLB-misses -c 2003";
+const char kPerfITLBMissCyclesCmdIvyBridge[] =
     "perf record -a -e itlb_misses.walk_duration -c 2003";
-const char kPerfRecordITLBMissCyclesCmdAtom[] =
+const char kPerfITLBMissCyclesCmdSkylake[] =
+    "perf record -a -e itlb_misses.walk_pending -c 2003";
+const char kPerfITLBMissCyclesCmdAtom[] =
     "perf record -a -e page_walks.i_side_cycles -c 2003";
-const char kPerfRecordCacheMissesCmd[] =
-    "perf record -a -e cache-misses -c 10007";
+const char kPerfCacheMissesCmd[] = "perf record -a -e cache-misses -c 10007";
 
 // Converts a protobuf to serialized format as a byte vector.
 std::vector<uint8_t> SerializeMessageToVector(
@@ -345,27 +347,27 @@
   cpuid.family = 0x06;
   cpuid.model = 0x3a;  // IvyBridge
   cpuid.model_name = "";
+  cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
-  EXPECT_EQ(cmds[1].value, kPerfRecordCallgraphCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordLBRCmd;
+                     return cmd.value == kPerfLBRCmd;
                    });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordCacheMissesCmd;
+                         return cmd.value == kPerfCacheMissesCmd;
                        });
   EXPECT_NE(cmds.end(), found);
-  found =
-      std::find_if(cmds.begin(), cmds.end(),
-                   [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordITLBMissCyclesCmdIvyBridge;
-                   });
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfITLBMissCyclesCmdIvyBridge;
+                       });
   EXPECT_NE(cmds.end(), found);
 }
 
@@ -376,27 +378,97 @@
   cpuid.family = 0x06;
   cpuid.model = 0x2a;  // SandyBridge
   cpuid.model_name = "";
+  cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
-  EXPECT_EQ(cmds[1].value, kPerfRecordCallgraphCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordLBRCmd;
+                     return cmd.value == kPerfLBRCmd;
                    });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordCacheMissesCmd;
+                         return cmd.value == kPerfCacheMissesCmd;
                        });
   EXPECT_NE(cmds.end(), found);
-  found =
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfITLBMissCyclesCmdIvyBridge;
+                       });
+  EXPECT_NE(cmds.end(), found);
+}
+
+TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Haswell) {
+  CPUIdentity cpuid;
+  cpuid.arch = "x86_64";
+  cpuid.vendor = "GenuineIntel";
+  cpuid.family = 0x06;
+  cpuid.model = 0x45;  // Haswell
+  cpuid.model_name = "";
+  cpuid.release = "3.8.11";
+  std::vector<RandomSelector::WeightAndValue> cmds =
+      internal::GetDefaultCommandsForCpu(cpuid);
+  ASSERT_GE(cmds.size(), 2UL);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
+  // No LBR callstacks because the kernel is old.
+  auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordITLBMissCyclesCmdIvyBridge;
+                     return cmd.value == kPerfLBRCallgraphCmd;
                    });
+  EXPECT_EQ(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfLBRCmd;
+                       });
+  EXPECT_NE(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfCacheMissesCmd;
+                       });
+  EXPECT_NE(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfITLBMissCyclesCmdIvyBridge;
+                       });
+  EXPECT_NE(cmds.end(), found);
+}
+
+TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_Skylake) {
+  CPUIdentity cpuid;
+  cpuid.arch = "x86_64";
+  cpuid.vendor = "GenuineIntel";
+  cpuid.family = 0x06;
+  cpuid.model = 0x4E;  // Skylake
+  cpuid.model_name = "";
+  cpuid.release = "3.18.0";
+  std::vector<RandomSelector::WeightAndValue> cmds =
+      internal::GetDefaultCommandsForCpu(cpuid);
+  ASSERT_GE(cmds.size(), 2UL);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  // We have both FP and LBR based callstacks.
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
+  EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphCmd);
+  auto found =
+      std::find_if(cmds.begin(), cmds.end(),
+                   [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                     return cmd.value == kPerfLBRCmd;
+                   });
+  EXPECT_NE(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfCacheMissesCmd;
+                       });
+  EXPECT_NE(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfITLBMissCyclesCmdSkylake;
+                       });
   EXPECT_NE(cmds.end(), found);
 }
 
@@ -407,35 +479,42 @@
   cpuid.family = 0x06;
   cpuid.model = 0x5c;  // Goldmont
   cpuid.model_name = "";
+  cpuid.release = "4.4.196";
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
-  EXPECT_EQ(cmds[1].value, kPerfRecordCallgraphCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
+  // No LBR callstacks because the microarchitecture doesn't support it.
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordLBRCmdAtom;
+                     return cmd.value == kPerfLBRCallgraphCmd;
                    });
-  EXPECT_NE(cmds.end(), found);
+  EXPECT_EQ(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordCacheMissesCmd;
+                         return cmd.value == kPerfLBRCmdAtom;
                        });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordDataTLBMissesCmd;
+                         return cmd.value == kPerfCacheMissesCmd;
+                       });
+  EXPECT_NE(cmds.end(), found);
+  found = std::find_if(cmds.begin(), cmds.end(),
+                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
+                         return cmd.value == kPerfDataTLBMissesCmd;
                        });
   EXPECT_EQ(cmds.end(), found) << "Goldmont requires specialized dTLB command";
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordDataTLBMissesCmdGLM;
+                         return cmd.value == kPerfDataTLBMissesCmdGLM;
                        });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordITLBMissCyclesCmdAtom;
+                         return cmd.value == kPerfITLBMissCyclesCmdAtom;
                        });
   EXPECT_NE(cmds.end(), found);
 }
@@ -450,17 +529,17 @@
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
-  EXPECT_EQ(cmds[1].value, kPerfRecordCallgraphCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordLBRCmd;
+                     return cmd.value == kPerfLBRCmd;
                    });
   EXPECT_EQ(cmds.end(), found) << "ARM does not support this command";
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordCacheMissesCmd;
+                         return cmd.value == kPerfCacheMissesCmd;
                        });
   EXPECT_EQ(cmds.end(), found) << "ARM does not support this command";
 }
@@ -475,17 +554,17 @@
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
-  EXPECT_EQ(cmds[1].value, kPerfRecordCallgraphCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfRecordLBRCmd;
+                     return cmd.value == kPerfLBRCmd;
                    });
   EXPECT_EQ(cmds.end(), found) << "x86_32 does not support this command";
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordCacheMissesCmd;
+                         return cmd.value == kPerfCacheMissesCmd;
                        });
   EXPECT_EQ(cmds.end(), found) << "x86_32 does not support this command";
 }
@@ -500,7 +579,7 @@
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   EXPECT_EQ(1UL, cmds.size());
-  EXPECT_EQ(cmds[0].value, kPerfRecordCyclesCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
 }
 
 TEST_F(PerfCollectorTest, CommandMatching_Empty) {
diff --git a/chrome/browser/portal/OWNERS b/chrome/browser/portal/OWNERS
new file mode 100644
index 0000000..bf4f802
--- /dev/null
+++ b/chrome/browser/portal/OWNERS
@@ -0,0 +1,3 @@
+file://third_party/blink/renderer/core/html/portal/OWNERS
+
+# COMPONENT: Blink>HTML>Portal
diff --git a/chrome/browser/portal/portal_browsertest.cc b/chrome/browser/portal/portal_browsertest.cc
index 3d398b0..82b0ddd 100644
--- a/chrome/browser/portal/portal_browsertest.cc
+++ b/chrome/browser/portal/portal_browsertest.cc
@@ -30,13 +30,7 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-// TODO(crbug.com/1006633): Test fails on Chrome OS.
-#if defined(OS_CHROMEOS)
-#define MAYBE_PortalActivation DISABLED_PortalActivation
-#else
-#define MAYBE_PortalActivation PortalActivation
-#endif
-IN_PROC_BROWSER_TEST_F(PortalBrowserTest, MAYBE_PortalActivation) {
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, PortalActivation) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url(embedded_test_server()->GetURL("/portal/activate.html"));
   ui_test_utils::NavigateToURL(browser(), url);
@@ -55,16 +49,8 @@
   EXPECT_EQ(portal_contents, tab_strip_model->GetActiveWebContents());
 }
 
-// TODO(crbug.com/1006633): Test fails on Chrome OS.
-#if defined(OS_CHROMEOS)
-#define MAYBE_DevToolsWindowStaysOpenAfterActivation \
-  DISABLED_DevToolsWindowStaysOpenAfterActivation
-#else
-#define MAYBE_DevToolsWindowStaysOpenAfterActivation \
-  DevToolsWindowStaysOpenAfterActivation
-#endif
 IN_PROC_BROWSER_TEST_F(PortalBrowserTest,
-                       MAYBE_DevToolsWindowStaysOpenAfterActivation) {
+                       DevToolsWindowStaysOpenAfterActivation) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url(embedded_test_server()->GetURL("/portal/activate.html"));
   ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 6dbbacc3..d7afecc 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -1776,15 +1776,6 @@
   PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
 }
 
-// Checks that deferred redirects in a synchronous XHR abort the prerender.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredSynchronousXHR) {
-  // Disable load event checks because they race with cancellation.
-  DisableLoadEventCheck();
-  PrerenderTestURL("/prerender/prerender_deferred_sync_xhr.html",
-                   FINAL_STATUS_BAD_DEFERRED_REDIRECT, 0);
-  ui_test_utils::NavigateToURL(current_browser(), dest_url());
-}
-
 // Checks that prerenders are not swapped for navigations with extra headers.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExtraHeadersNoSwap) {
   PrerenderTestURL("/prerender/prerender_page.html",
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 02e437c..7b78fb61 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -719,10 +719,6 @@
   ReportUnsupportedPrerenderScheme(url);
 }
 
-void PrerenderContents::CancelPrerenderForSyncDeferredRedirect() {
-  Destroy(FINAL_STATUS_BAD_DEFERRED_REDIRECT);
-}
-
 void PrerenderContents::OnPrerenderCancelerReceiver(
     mojo::PendingReceiver<chrome::mojom::PrerenderCanceler> receiver) {
   if (!prerender_canceler_receiver_.is_bound())
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 46e9f6bf..ffab332 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -41,7 +41,7 @@
 class RenderViewHost;
 class SessionStorageNamespace;
 class WebContents;
-}
+}  // namespace content
 
 namespace history {
 struct HistoryAddPageArgs;
@@ -294,7 +294,6 @@
   // chrome::mojom::PrerenderCanceler:
   void CancelPrerenderForUnsupportedMethod() override;
   void CancelPrerenderForUnsupportedScheme(const GURL& url) override;
-  void CancelPrerenderForSyncDeferredRedirect() override;
 
   mojo::Receiver<chrome::mojom::PrerenderCanceler> prerender_canceler_receiver_{
       this};
diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h
index 4673f4a..0eec8c2d 100644
--- a/chrome/browser/prerender/prerender_final_status.h
+++ b/chrome/browser/prerender/prerender_final_status.h
@@ -62,7 +62,7 @@
   FINAL_STATUS_REGISTER_PROTOCOL_HANDLER = 42,
   // Obsolete: FINAL_STATUS_CREATING_AUDIO_STREAM = 43,
   // Obsolete: FINAL_STATUS_PAGE_BEING_CAPTURED = 44,
-  FINAL_STATUS_BAD_DEFERRED_REDIRECT = 45,
+  // Obsolete: FINAL_STATUS_BAD_DEFERRED_REDIRECT = 45,
   // Obsolete: FINAL_STATUS_NAVIGATION_UNCOMMITTED = 46,
   // Obsolete: FINAL_STATUS_NEW_NAVIGATION_ENTRY = 47,
   // Obsolete: FINAL_STATUS_COOKIE_STORE_NOT_LOADED = 48,
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 7bf6df9..9bc8457 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -603,6 +603,21 @@
   return result;
 }
 
+std::vector<WebContents*>
+PrerenderManager::GetAllNoStatePrefetchingContentsForTesting() const {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  std::vector<WebContents*> result;
+
+  for (const auto& prerender : active_prerenders_) {
+    WebContents* contents = prerender->contents()->prerender_contents();
+    if (contents && prerender->contents()->prerender_mode() == PREFETCH_ONLY) {
+      result.push_back(contents);
+    }
+  }
+
+  return result;
+}
+
 bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin,
                                                   const GURL& url) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 05e0cc0..ddc3912 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -267,6 +267,10 @@
   // Returns a list of all WebContents being prerendered.
   std::vector<content::WebContents*> GetAllPrerenderingContents() const;
 
+  // Returns a list of all WebContents being NoStatePrefetched.
+  std::vector<content::WebContents*>
+  GetAllNoStatePrefetchingContentsForTesting() const;
+
   // Checks whether |url| has been recently navigated to.
   bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url);
 
diff --git a/chrome/browser/profiles/OWNERS b/chrome/browser/profiles/OWNERS
index 00ef995..44fcf3b 100644
--- a/chrome/browser/profiles/OWNERS
+++ b/chrome/browser/profiles/OWNERS
@@ -16,5 +16,9 @@
 
 per-file host_zoom_map_browsertest.cc=wjmaclean@chromium.org
 
+per-file gaia_info_update_service*=msalama@chromium.org
+per-file profile_attributes*=msalama@chromium.org
+per-file profile_info*=msalama@chromium.org
+
 # COMPONENT: UI>Browser>Profiles
 # TEAM: chrome-signin@chromium.org
diff --git a/chrome/browser/profiles/gaia_info_update_service.cc b/chrome/browser/profiles/gaia_info_update_service.cc
index c7b3e0a..894f4742 100644
--- a/chrome/browser/profiles/gaia_info_update_service.cc
+++ b/chrome/browser/profiles/gaia_info_update_service.cc
@@ -69,7 +69,7 @@
   auto maybe_account_info =
       identity_manager_
           ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              identity_manager_->GetUnconsentedPrimaryAccountInfo().account_id);
+              unconsented_primary_account_info.account_id);
   if (maybe_account_info.has_value())
     Update(maybe_account_info.value());
 }
@@ -139,7 +139,13 @@
 
 void GAIAInfoUpdateService::OnPrimaryAccountCleared(
     const CoreAccountInfo& previous_primary_account_info) {
-  ClearProfileEntry();
+  // Do not clear the profile if there is an unconsented primary account.
+  if (!ShouldUpdate()) {
+    ClearProfileEntry();
+    return;
+  }
+  DCHECK_EQ(identity_manager_->GetUnconsentedPrimaryAccountInfo().gaia,
+            previous_primary_account_info.gaia);
 }
 
 void GAIAInfoUpdateService::OnUnconsentedPrimaryAccountChanged(
diff --git a/chrome/browser/profiles/gaia_info_update_service_unittest.cc b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
index cb0e0cb..0ca2ab1 100644
--- a/chrome/browser/profiles/gaia_info_update_service_unittest.cc
+++ b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
@@ -163,6 +163,36 @@
 }
 
 #if !defined(ANDROID)
+TEST_F(GAIAInfoUpdateServiceTest, SyncOnSyncOffKeepAllAccounts) {
+  AccountInfo info =
+      identity_test_env()->MakeAccountAvailable("pat@example.com");
+  base::RunLoop().RunUntilIdle();
+  identity_test_env()->SetPrimaryAccount(info.email);
+  info = GetValidAccountInfo(info.email, info.account_id, "Pat", "Pat Foo");
+  signin::UpdateAccountInfoForAccount(identity_test_env()->identity_manager(),
+                                      info);
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_EQ(1u, storage()->GetNumberOfProfiles());
+  ProfileAttributesEntry* entry = storage()->GetAllProfilesAttributes().front();
+  gfx::Image gaia_picture = gfx::test::CreateImage(256, 256);
+  signin::SimulateAccountImageFetch(identity_test_env()->identity_manager(),
+                                    info.account_id, gaia_picture);
+  // Turn off sync but stay logged in.
+  identity_test_env()->ClearPrimaryAccount(
+      signin::ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS);
+  ASSERT_TRUE(
+      identity_test_env()->identity_manager()->HasUnconsentedPrimaryAccount());
+  // Verify that the GAIA name and picture, and picture URL are not cleared
+  // as unconsented primary account still exists.
+  EXPECT_EQ(entry->GetGAIAGivenName(), base::UTF8ToUTF16("Pat"));
+  EXPECT_EQ(entry->GetGAIAName(), base::UTF8ToUTF16("Pat Foo"));
+  EXPECT_EQ(
+      profile()->GetPrefs()->GetString(prefs::kGoogleServicesHostedDomain),
+      info.hosted_domain);
+  EXPECT_TRUE(gfx::test::AreImagesEqual(gaia_picture, entry->GetAvatarIcon()));
+}
+
 TEST_F(GAIAInfoUpdateServiceTest, LogInLogOut) {
   std::string email = "pat@example.com";
   AccountInfo info = identity_test_env()->MakeAccountAvailableWithCookies(
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc
index 7a1bb02..62035f2c 100644
--- a/chrome/browser/profiles/profile_attributes_entry.cc
+++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -32,6 +32,7 @@
 const char kPasswordTokenKey[] = "gaia_password_token";
 const char kIsAuthErrorKey[] = "is_auth_error";
 const char kMetricsBucketIndex[] = "metrics_bucket_index";
+const char kSigninRequiredKey[] = "signin_required";
 
 // Local state pref to keep track of the next available profile bucket.
 const char kNextMetricsBucketIndex[] = "profile.metrics.next_bucket_index";
@@ -289,7 +290,7 @@
 }
 
 std::string ProfileAttributesEntry::GetGAIAId() const {
-  return profile_info_cache_->GetGAIAIdOfProfileAtIndex(profile_index());
+  return GetString(ProfileAttributesEntry::kGAIAIdKey);
 }
 
 const gfx::Image* ProfileAttributesEntry::GetGAIAPicture() const {
@@ -327,8 +328,7 @@
 }
 
 bool ProfileAttributesEntry::IsSigninRequired() const {
-  return profile_info_cache_->ProfileIsSigninRequiredAtIndex(profile_index()) ||
-         is_force_signin_profile_locked_;
+  return GetBool(kSigninRequiredKey) || is_force_signin_profile_locked_;
 }
 
 std::string ProfileAttributesEntry::GetSupervisedUserId() const {
@@ -445,7 +445,10 @@
 }
 
 void ProfileAttributesEntry::SetIsSigninRequired(bool value) {
-  profile_info_cache_->SetProfileSigninRequiredAtIndex(profile_index(), value);
+  if (value != GetBool(kSigninRequiredKey)) {
+    SetBool(kSigninRequiredKey, value);
+    profile_info_cache_->NotifyIsSigninRequiredChanged(GetPath());
+  }
   if (is_force_signin_enabled_)
     LockForceSigninProfile(value);
 }
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index 3cfbf404..3e972584 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -43,7 +43,6 @@
 const char kIsUsingDefaultAvatarKey[] = "is_using_default_avatar";
 const char kUseGAIAPictureKey[] = "use_gaia_picture";
 const char kGAIAPictureFileNameKey[] = "gaia_picture_file_name";
-const char kSigninRequiredKey[] = "signin_required";
 const char kAccountIdKey[] = "account_id_key";
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 const char kLegacyProfileNameMigrated[] = "legacy.profile.name.migrated";
@@ -256,14 +255,6 @@
   return user_data_dir_.AppendASCII(keys_[index]);
 }
 
-std::string ProfileInfoCache::GetGAIAIdOfProfileAtIndex(
-    size_t index) const {
-  std::string gaia_id;
-  GetInfoForProfileAtIndex(index)->GetString(ProfileAttributesEntry::kGAIAIdKey,
-                                             &gaia_id);
-  return gaia_id;
-}
-
 const gfx::Image* ProfileInfoCache::GetGAIAPictureOfProfileAtIndex(
     size_t index) const {
   base::FilePath path = GetPathOfProfileAtIndex(index);
@@ -292,12 +283,6 @@
   return value;
 }
 
-bool ProfileInfoCache::ProfileIsSigninRequiredAtIndex(size_t index) const {
-  bool value = false;
-  GetInfoForProfileAtIndex(index)->GetBoolean(kSigninRequiredKey, &value);
-  return value;
-}
-
 bool ProfileInfoCache::ProfileIsUsingDefaultAvatarAtIndex(size_t index) const {
   bool value = false;
   GetInfoForProfileAtIndex(index)->GetBoolean(kIsUsingDefaultAvatarKey, &value);
@@ -406,18 +391,6 @@
     observer.OnProfileAvatarChanged(profile_path);
 }
 
-void ProfileInfoCache::SetProfileSigninRequiredAtIndex(size_t index,
-                                                       bool value) {
-  if (value == ProfileIsSigninRequiredAtIndex(index))
-    return;
-
-  std::unique_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetBoolean(kSigninRequiredKey, value);
-  SetInfoForProfileAtIndex(index, std::move(info));
-  NotifyIsSigninRequiredChanged(GetPathOfProfileAtIndex(index));
-}
-
 void ProfileInfoCache::SetProfileIsUsingDefaultAvatarAtIndex(
     size_t index, bool value) {
   if (value == ProfileIsUsingDefaultAvatarAtIndex(index))
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index cbcb3dc..76691cb 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -76,13 +76,11 @@
       const base::FilePath& profile_path) const override;
   // Will be removed SOON with ProfileInfoCache tests. Do not use!
   base::FilePath GetPathOfProfileAtIndex(size_t index) const override;
-  std::string GetGAIAIdOfProfileAtIndex(size_t index) const override;
   // Returns the GAIA picture for the given profile. This may return NULL
   // if the profile does not have a GAIA picture or if the picture must be
   // loaded from disk.
   const gfx::Image* GetGAIAPictureOfProfileAtIndex(size_t index) const override;
   bool IsUsingGAIAPictureOfProfileAtIndex(size_t index) const override;
-  bool ProfileIsSigninRequiredAtIndex(size_t index) const override;
   bool ProfileIsUsingDefaultAvatarAtIndex(size_t index) const override;
 
   // Returns true if a GAIA picture has been loaded or has failed to load for
@@ -96,7 +94,6 @@
   void SetSupervisedUserIdOfProfileAtIndex(size_t index, const std::string& id);
   void SetGAIAPictureOfProfileAtIndex(size_t index, gfx::Image image);
   void SetIsUsingGAIAPictureOfProfileAtIndex(size_t index, bool value);
-  void SetProfileSigninRequiredAtIndex(size_t index, bool value);
   void SetProfileIsUsingDefaultAvatarAtIndex(size_t index, bool value);
 
   // Notify IsSignedInRequired to all observer
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc
index 7f2ed5e9..b8f9f6a 100644
--- a/chrome/browser/profiles/profile_info_cache_unittest.cc
+++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -426,7 +426,7 @@
   std::string new_gaia_id = "12345";
   entry_2->SetAuthInfo(new_gaia_id, new_user_name, true);
   EXPECT_EQ(new_user_name, entry_2->GetUserName());
-  EXPECT_EQ(new_gaia_id, GetCache()->GetGAIAIdOfProfileAtIndex(1));
+  EXPECT_EQ(new_gaia_id, entry_2->GetGAIAId());
   EXPECT_NE(new_user_name, entry_1->GetUserName());
 
   // Avatar icons not used on Android.
diff --git a/chrome/browser/profiles/profile_info_interface.h b/chrome/browser/profiles/profile_info_interface.h
index 1f3e7c2..7dd9586 100644
--- a/chrome/browser/profiles/profile_info_interface.h
+++ b/chrome/browser/profiles/profile_info_interface.h
@@ -28,18 +28,12 @@
 
   virtual base::FilePath GetPathOfProfileAtIndex(size_t index) const = 0;
 
-
-  virtual std::string GetGAIAIdOfProfileAtIndex(size_t index) const = 0;
-
   virtual const gfx::Image* GetGAIAPictureOfProfileAtIndex(
       size_t index) const = 0;
 
   // Checks if the GAIA picture should be used as the profile's avatar icon.
   virtual bool IsUsingGAIAPictureOfProfileAtIndex(size_t index) const = 0;
 
-  // This profile is associated with an account but has been signed-out.
-  virtual bool ProfileIsSigninRequiredAtIndex(size_t index) const = 0;
-
   // Returns true if the user has never manually selected a profile avatar.
   virtual bool ProfileIsUsingDefaultAvatarAtIndex(size_t index) const = 0;
 
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index bc6769b..cc1d53d 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -473,18 +473,6 @@
           id <= IDC_OPEN_LINK_IN_PROFILE_LAST);
 }
 
-// Usually a new tab is expected where this function is used,
-// however users should be able to open a tab in background
-// or in a new window.
-WindowOpenDisposition ForceNewTabDispositionFromEventFlags(
-    int event_flags) {
-  WindowOpenDisposition disposition =
-      ui::DispositionFromEventFlags(event_flags);
-  return disposition == WindowOpenDisposition::CURRENT_TAB
-             ? WindowOpenDisposition::NEW_FOREGROUND_TAB
-             : disposition;
-}
-
 // Returns the preference of the profile represented by the |context|.
 PrefService* GetPrefs(content::BrowserContext* context) {
   return user_prefs::UserPrefs::Get(context);
@@ -2400,7 +2388,8 @@
     case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
     case IDC_CONTENT_CONTEXT_GOTOURL:
       OpenURL(selection_navigation_url_, GURL(),
-              ForceNewTabDispositionFromEventFlags(event_flags),
+              ui::DispositionFromEventFlags(
+                  event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB),
               ui::PAGE_TRANSITION_LINK);
       break;
 
@@ -2724,8 +2713,8 @@
 
   base::RecordAction(
       UserMetricsAction("RegisterProtocolHandler.ContextMenu_Open"));
-  WindowOpenDisposition disposition =
-      ForceNewTabDispositionFromEventFlags(event_flags);
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   OpenURL(handlers[handler_index].TranslateUrl(params_.link_url),
           GetDocumentURL(params_),
           disposition,
@@ -3027,8 +3016,8 @@
 }
 
 void RenderViewContextMenu::ExecLanguageSettings(int event_flags) {
-  WindowOpenDisposition disposition =
-      ForceNewTabDispositionFromEventFlags(event_flags);
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
   OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK);
 }
@@ -3036,8 +3025,8 @@
 void RenderViewContextMenu::ExecProtocolHandlerSettings(int event_flags) {
   base::RecordAction(
       UserMetricsAction("RegisterProtocolHandler.ContextMenu_Settings"));
-  WindowOpenDisposition disposition =
-      ForceNewTabDispositionFromEventFlags(event_flags);
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   GURL url = chrome::GetSettingsUrl(chrome::kHandlerSettingsSubPage);
   OpenURL(url, GURL(), disposition, ui::PAGE_TRANSITION_LINK);
 }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 9cf5370..5d09fc4 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -1043,6 +1043,15 @@
 
 void TabLifecycleUnitSource::TabLifecycleUnit::OnVisibilityChanged(
     content::Visibility visibility) {
+  // Ensure that the tab is not considered focused when not visible.
+  //
+  // TabLifeycleUnitSource calls SetFocused(false) when focus changes to another
+  // tab. The code below is also required to cover the case where the focused
+  // tab is hidden but no other tab is focused, which can happen when the
+  // focused window is minimized or occluded.
+  if (visibility != content::Visibility::VISIBLE)
+    SetFocused(false);
+
   OnLifecycleUnitVisibilityChanged(visibility);
 }
 
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
index bbce56c..30eca383 100644
--- a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
@@ -536,7 +536,7 @@
   // Prerender some contents.
   prerender::test_utils::RestorePrerenderMode restore_prerender_mode;
   prerender::PrerenderManager::SetMode(
-      prerender::PrerenderManager::DEPRECATED_PRERENDER_MODE_ENABLED);
+      prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH);
   prerender::PrerenderManager* prerender_manager =
       prerender::PrerenderManagerFactory::GetForBrowserContext(profile());
   GURL url("http://www.example.com");
@@ -545,8 +545,9 @@
       prerender_manager->AddPrerenderFromOmnibox(
           url, contents1()->GetController().GetDefaultSessionStorageNamespace(),
           kSize));
+  EXPECT_NE(nullptr, prerender_handle);
   const std::vector<content::WebContents*> contentses =
-      prerender_manager->GetAllPrerenderingContents();
+      prerender_manager->GetAllNoStatePrefetchingContentsForTesting();
   ASSERT_EQ(1U, contentses.size());
 
   // Check that the visibility and loading state for a prerender WebContents is
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
index 65deae2..499ef169 100644
--- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -325,10 +325,12 @@
   void SetUpOnMainThread() override {
     TabManagerTest::SetUpOnMainThread();
 
+    ASSERT_TRUE(embedded_test_server()->Start());
+
     // Open 2 tabs with default URLs in a focused tab strip.
     GetTabLifecycleUnitSource()->SetFocusedTabStripModelForTesting(tsm());
-    OpenTwoTabs(GURL(chrome::kChromeUIAboutURL),
-                GURL(chrome::kChromeUICreditsURL));
+    OpenTwoTabs(embedded_test_server()->GetURL("/title2.html"),
+                embedded_test_server()->GetURL("/title3.html"));
   }
 
  private:
@@ -1488,71 +1490,66 @@
 
 }  // namespace
 
-// Flaky on Linux.  Times out on Windows and Mac debug builds.
-// http://crbug.com/772839.
-#if defined(OS_LINUX) || \
-    ((defined(OS_WIN) || defined(OS_MACOSX)) && !defined(NDEBUG))
-#define MAYBE_DiscardTabsWithMinimizedAndOccludedWindows \
-  DISABLED_DiscardTabsWithMinimizedAndOccludedWindows
-#else
-#define MAYBE_DiscardTabsWithMinimizedAndOccludedWindows \
-  DiscardTabsWithMinimizedAndOccludedWindows
-#endif
-IN_PROC_BROWSER_TEST_F(TabManagerTest,
-                       MAYBE_DiscardTabsWithMinimizedAndOccludedWindows) {
-  // Covered by |browser2|.
-  Browser* browser1 = browser();
-  EnsureTabsInBrowser(browser1, 2);
-  browser1->window()->SetBounds(gfx::Rect(10, 10, 10, 10));
-  // Covers |browser1|.
-  Browser* browser2 = CreateBrowserWithTabs(2);
-  EXPECT_NE(browser1, browser2);
-  browser2->window()->SetBounds(gfx::Rect(0, 0, 100, 100));
-  // Active browser.
-  Browser* browser3 = CreateBrowserWithTabs(2);
-  EXPECT_NE(browser1, browser3);
-  EXPECT_NE(browser2, browser3);
-  browser3->window()->SetBounds(gfx::Rect(110, 0, 100, 100));
+IN_PROC_BROWSER_TEST_F(TabManagerTest, DiscardTabsWithMinimizedWindow) {
   // Minimized browser.
-  Browser* browser4 = CreateBrowserWithTabs(2);
-  browser4->window()->Minimize();
-  EXPECT_NE(browser1, browser4);
-  EXPECT_NE(browser2, browser4);
-  EXPECT_NE(browser3, browser4);
+  EnsureTabsInBrowser(browser(), 2);
+  browser()->window()->Minimize();
+  // Other browser that will be last active. This browser exists because the
+  // last active tab cannot be discarded on
 
   // Advance time so everything is urgent discardable.
   test_clock_.Advance(kBackgroundUrgentProtectionTime);
 
-  for (int i = 0; i < 8; ++i)
-    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::PROACTIVE);
+  for (int i = 0; i < 2; ++i)
+    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::URGENT);
 
   base::RunLoop().RunUntilIdle();
 
 // On ChromeOS, active tabs are discarded if their window is non-visible. On
 // other platforms, they are never discarded.
 #if defined(OS_CHROMEOS)
-  EXPECT_TRUE(IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_FALSE(
-      IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_FALSE(
-      IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_TRUE(IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_TRUE(
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
 #else
   EXPECT_FALSE(
-      IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_FALSE(
-      IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_FALSE(
-      IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(0)));
-  EXPECT_FALSE(
-      IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(0)));
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
 #endif
 
   // Non-active tabs can be discarded on all platforms.
-  EXPECT_TRUE(IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(1)));
-  EXPECT_TRUE(IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(1)));
-  EXPECT_TRUE(IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(1)));
-  EXPECT_TRUE(IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(1)));
+  EXPECT_TRUE(
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(1)));
+}
+
+IN_PROC_BROWSER_TEST_F(TabManagerTest, DiscardTabsWithOccludedWindow) {
+  // Occluded browser.
+  EnsureTabsInBrowser(browser(), 2);
+  browser()->window()->SetBounds(gfx::Rect(10, 10, 10, 10));
+  // Other browser that covers the occluded browser.
+  Browser* other_browser = CreateBrowserWithTabs(1);
+  EXPECT_NE(other_browser, browser());
+  other_browser->window()->SetBounds(gfx::Rect(0, 0, 100, 100));
+
+  // Advance time so everything is urgent discardable.
+  test_clock_.Advance(kBackgroundUrgentProtectionTime);
+
+  for (int i = 0; i < 3; ++i)
+    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::URGENT);
+
+  base::RunLoop().RunUntilIdle();
+
+// On ChromeOS, active tabs are discarded if their window is non-visible. On
+// other platforms, they are never discarded.
+#if defined(OS_CHROMEOS)
+  EXPECT_TRUE(
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
+#else
+  EXPECT_FALSE(
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
+#endif
+
+  // Non-active tabs can be discarded on all platforms.
+  EXPECT_TRUE(
+      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(1)));
 }
 
 IN_PROC_BROWSER_TEST_F(TabManagerTest, UnfreezeTabOnNavigationEvent) {
diff --git a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
index fe42ce4..7210924 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
@@ -53,6 +53,9 @@
 js_library("gallerybutton") {
   deps = [
     ":chrome_util",
+    "models:filesystem",
+    "models:result_saver",
+    "models:video_saver",
   ]
   externs_list = [
     "$externs_path/file_manager_private.js",
diff --git a/chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js b/chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js
index 7e28300..5f7ddbeac 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js
@@ -2,17 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
+import {assert, assertInstanceof} from './chrome_util.js';
+import {FileVideoSaver} from './models/file_video_saver.js';
+import * as filesystem from './models/filesystem.js';
+// eslint-disable-next-line no-unused-vars
+import {ResultSaver} from './models/result_saver.js';
+import * as util from './util.js';
 
 /**
- * Namespace for the Camera app.
+ * Width of thumbnail used by cover photo of gallery button.
+ * @type {number}
  */
-var cca = cca || {};
+const THUMBNAIL_WIDTH = 240;
 
 /**
  * Cover photo of gallery button.
  */
-cca.CoverPhoto = class {
+class CoverPhoto {
   /**
    * @param {!FileEntry} file File entry of cover photo.
    * @param {!string} thumbnailUrl Url to its thumbnail.
@@ -49,38 +55,31 @@
   /**
    * Creates CoverPhoto objects from photo file.
    * @param {!FileEntry} file
-   * @return {!Promise<!cca.CoverPhoto>}
+   * @return {!Promise<!CoverPhoto>}
    */
   static async create(file) {
-    const fileUrl = await cca.models.FileSystem.pictureURL(file);
-    const isVideo = cca.models.FileSystem.hasVideoPrefix(file);
-    const thumbnail = await cca.util.scalePicture(
-        fileUrl, isVideo, cca.CoverPhoto.THUMBNAIL_WIDTH);
+    const fileUrl = await filesystem.pictureURL(file);
+    const isVideo = filesystem.hasVideoPrefix(file);
+    const thumbnail =
+        await util.scalePicture(fileUrl, isVideo, THUMBNAIL_WIDTH);
     URL.revokeObjectURL(fileUrl);
 
-    return new cca.CoverPhoto(file, URL.createObjectURL(thumbnail));
+    return new CoverPhoto(file, URL.createObjectURL(thumbnail));
   }
-};
-
-/**
- * Width of thumbnail.
- * @type {number}
- * @const
- */
-cca.CoverPhoto.THUMBNAIL_WIDTH = 240;
+}
 
 /**
  * Creates a controller for the gallery-button.
- * @implements {cca.models.ResultSaver}
+ * @implements {ResultSaver}
  */
-cca.GalleryButton = class {
+export class GalleryButton {
   /**
    * @public
    */
   constructor() {
     /**
      * Cover photo from latest saved picture.
-     * @type {?cca.CoverPhoto}
+     * @type {?CoverPhoto}
      * @private
      */
     this.cover_ = null;
@@ -89,7 +88,7 @@
      * @type {!HTMLButtonElement}
      * @private
      */
-    this.button_ = cca.assertInstanceof(
+    this.button_ = assertInstanceof(
         document.querySelector('#gallery-enter'), HTMLButtonElement);
 
     /**
@@ -126,7 +125,7 @@
    * @private
    */
   async updateCover_(file) {
-    const cover = file === null ? null : await cca.CoverPhoto.create(file);
+    const cover = file === null ? null : await CoverPhoto.create(file);
     if (this.cover_ === cover) {
       return;
     }
@@ -152,25 +151,24 @@
 
     // Checks existence of cached cover photo.
     if (this.cover_ !== null) {
-      const file = await cca.models.FileSystem.getFile(
-          dir, this.cover_.name, /* create */ false);
+      const file =
+          await filesystem.getFile(dir, this.cover_.name, /* create */ false);
       if (file !== null) {
         return;
       }
     }
 
     // Rescan file system.
-    const files = await cca.models.FileSystem.getEntries();
+    const files = await filesystem.getEntries();
     if (files.length === 0) {
       await this.updateCover_(null);
       return;
     }
-    const filesWithTime = await Promise.all(files.map(
-        async (file) => ({
-          file,
-          time:
-              (await cca.models.FileSystem.getMetadata(file)).modificationTime,
-        })));
+    const filesWithTime = await Promise.all(
+        files.map(async (file) => ({
+                    file,
+                    time: (await filesystem.getMetadata(file)).modificationTime,
+                  })));
     const lastFile =
         filesWithTime.reduce((last, cur) => last.time > cur.time ? last : cur)
             .file;
@@ -205,10 +203,10 @@
       // nothing.
       // TODO(yuli): Support showing images by EXIF orientation
       // instead.
-      cca.util.orientPhoto(blob, resolve, () => resolve(blob));
+      util.orientPhoto(blob, resolve, () => resolve(blob));
     });
-    const file = await cca.models.FileSystem.saveBlob(orientedPhoto, name);
-    cca.assert(file !== null);
+    const file = await filesystem.saveBlob(orientedPhoto, name);
+    assert(file !== null);
     await this.updateCover_(file);
   }
 
@@ -216,8 +214,8 @@
    * @override
    */
   async startSaveVideo() {
-    const tempFile = await cca.models.FileSystem.createTempVideoFile();
-    return cca.models.FileVideoSaver.create(tempFile);
+    const tempFile = await filesystem.createTempVideoFile();
+    return FileVideoSaver.create(tempFile);
   }
 
   /**
@@ -225,8 +223,13 @@
    */
   async finishSaveVideo(video, name) {
     const tempFile = await video.endWrite();
-    const file = await cca.models.FileSystem.saveVideo(tempFile, name);
-    cca.assert(file !== null);
+    const file = await filesystem.saveVideo(tempFile, name);
+    assert(file !== null);
     await this.updateCover_(file);
   }
-};
+}
+
+/**
+ * @typedef {GalleryButton}
+ */
+cca.GalleryButton = GalleryButton;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/metrics.js b/chrome/browser/resources/chromeos/camera/src/js/metrics.js
index 4427b8c5..aebc0813 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/metrics.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/metrics.js
@@ -2,26 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for metrics.
- */
-cca.metrics = cca.metrics || {};
+import * as state from './state.js';
+import {Mode,
+        Resolution,  // eslint-disable-line no-unused-vars
+} from './type.js';
 
 /**
  * Event builder for basic metrics.
  * @type {?analytics.EventBuilder}
- * @private
  */
-cca.metrics.base_ = null;
+let base = null;
 
-var analytics = window['analytics'] || {};
+/* global analytics */
 
 /**
  * Fixes analytics.EventBuilder's dimension() method.
@@ -37,15 +29,14 @@
  * Promise for Google Analytics tracker.
  * @type {Promise<analytics.Tracker>}
  * @suppress {checkTypes}
- * @private
  */
-cca.metrics.ga_ = (function() {
+const ga = (function() {
   const id = 'UA-134822711-1';
   const service = analytics.getService('chrome-camera-app');
 
-  var getConfig = () =>
+  const getConfig = () =>
       new Promise((resolve) => service.getConfig().addCallback(resolve));
-  var checkEnabled = () => {
+  const checkEnabled = () => {
     return new Promise((resolve) => {
       try {
         chrome.metricsPrivate.getIsCrashReportingEnabled(resolve);
@@ -54,7 +45,7 @@
       }
     });
   };
-  var initBuilder = () => {
+  const initBuilder = () => {
     return new Promise((resolve) => {
              try {
                chrome.chromeosInfoPrivate.get(
@@ -64,12 +55,12 @@
              }
            })
         .then((board) => {
-          var boardName = /^(x86-)?(\w*)/.exec(board)[0];
-          var match = navigator.appVersion.match(/CrOS\s+\S+\s+([\d.]+)/);
-          var osVer = match ? match[1] : '';
-          cca.metrics.base_ = analytics.EventBuilder.builder()
-                                  .dimen(1, boardName)
-                                  .dimen(2, osVer);
+          const boardName = /^(x86-)?(\w*)/.exec(board)[0];
+          const match = navigator.appVersion.match(/CrOS\s+\S+\s+([\d.]+)/);
+          const osVer = match ? match[1] : '';
+          base = analytics.EventBuilder.builder()
+                     .dimen(1, boardName)
+                     .dimen(2, osVer);
         });
   };
 
@@ -84,18 +75,17 @@
  * Returns event builder for the metrics type: launch.
  * @param {boolean} ackMigrate Whether acknowledged to migrate during launch.
  * @return {!analytics.EventBuilder}
- * @private
  */
-cca.metrics.launchType_ = function(ackMigrate) {
-  return cca.metrics.base_.category('launch').action('start').label(
+function launchType(ackMigrate) {
+  return base.category('launch').action('start').label(
       ackMigrate ? 'ack-migrate' : '');
-};
+}
 
 /**
  * Types of intent result dimension.
  * @enum {string}
  */
-cca.metrics.IntentResultType = {
+export const IntentResultType = {
   NOT_INTENT: '',
   CANCELED: 'canceled',
   CONFIRMED: 'confirmed',
@@ -105,33 +95,30 @@
  * Returns event builder for the metrics type: capture.
  * @param {?string} facingMode Camera facing-mode of the capture.
  * @param {number} length Length of 1 minute buckets for captured video.
- * @param {!cca.Resolution} resolution Capture resolution.
- * @param {!cca.metrics.IntentResultType} intentResult
+ * @param {!Resolution} resolution Capture resolution.
+ * @param {!IntentResultType} intentResult
  * @return {!analytics.EventBuilder}
- * @private
  */
-cca.metrics.captureType_ = function(
-    facingMode, length, resolution, intentResult) {
+function captureType(facingMode, length, resolution, intentResult) {
   /**
-   * @param {!Array<cca.state.StateUnion>} states
-   * @param {cca.state.StateUnion=} cond
+   * @param {!Array<state.StateUnion>} states
+   * @param {state.StateUnion=} cond
    * @param {boolean=} strict
    * @return {string}
    */
   const condState = (states, cond = undefined, strict = undefined) => {
     // Return the first existing state among the given states only if there is
     // no gate condition or the condition is met.
-    const prerequisite = !cond || cca.state.get(cond);
+    const prerequisite = !cond || state.get(cond);
     if (strict && !prerequisite) {
       return '';
     }
-    return prerequisite && states.find((state) => cca.state.get(state)) ||
-        'n/a';
+    return prerequisite && states.find((s) => state.get(s)) || 'n/a';
   };
 
-  const State = cca.state.State;
-  return cca.metrics.base_.category('capture')
-      .action(condState(Object.values(cca.Mode)))
+  const State = state.State;
+  return base.category('capture')
+      .action(condState(Object.values(Mode)))
       .label(facingMode || '(not set)')
       // Skips 3rd dimension for obsolete 'sound' state.
       .dimen(4, condState([State.MIRROR]))
@@ -140,14 +127,14 @@
           condState(
               [State.GRID_3x3, State.GRID_4x4, State.GRID_GOLDEN], State.GRID))
       .dimen(6, condState([State.TIMER_3SEC, State.TIMER_10SEC], State.TIMER))
-      .dimen(7, condState([State.MIC], cca.Mode.VIDEO, true))
+      .dimen(7, condState([State.MIC], Mode.VIDEO, true))
       .dimen(8, condState([State.MAX_WND]))
       .dimen(9, condState([State.TALL]))
       .dimen(10, resolution.toString())
-      .dimen(11, condState([State.FPS_30, State.FPS_60], cca.Mode.VIDEO, true))
+      .dimen(11, condState([State.FPS_30, State.FPS_60], Mode.VIDEO, true))
       .dimen(12, intentResult)
       .value(length || 0);
-};
+}
 
 /**
  * Returns event builder for the metrics type: perf.
@@ -155,33 +142,39 @@
  * @param {number} duration The duration of the event in ms.
  * @param {Object=} extras Optional information for the event.
  * @return {!analytics.EventBuilder}
- * @private
  */
-cca.metrics.perfType_ = function(event, duration, extras = {}) {
+function perfType(event, duration, extras = {}) {
   const {resolution = ''} = extras;
-  return cca.metrics.base_.category('perf')
+  return base.category('perf')
       .action(event)
       // Round the duration here since GA expects that the value is an integer.
       // Reference: https://support.google.com/analytics/answer/1033068
       .value(Math.round(duration))
       .dimen(3, `${resolution}`);
-};
+}
 
 /**
  * Metrics types.
  * @enum {function(...): !analytics.EventBuilder}
  */
-cca.metrics.Type = {
-  LAUNCH: cca.metrics.launchType_,
-  CAPTURE: cca.metrics.captureType_,
-  PERF: cca.metrics.perfType_,
+export const Type = {
+  LAUNCH: launchType,
+  CAPTURE: captureType,
+  PERF: perfType,
 };
 
 /**
  * Logs the given metrics.
- * @param {!cca.metrics.Type} type Metrics type.
+ * @param {!Type} type Metrics type.
  * @param {...*} args Optional rest parameters for logging metrics.
  */
-cca.metrics.log = function(type, ...args) {
-  cca.metrics.ga_.then((tracker) => tracker.send(type(...args)));
-};
+export function log(type, ...args) {
+  ga.then((tracker) => tracker.send(type(...args)));
+}
+
+/** const */
+cca.metrics.IntentResultType = IntentResultType;
+/** const */
+cca.metrics.Type = Type;
+/** const */
+cca.metrics.log = log;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
index deb5bd2..071c848 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
@@ -21,6 +21,7 @@
 
 js_library("filesystem") {
   deps = [
+    ":filenamer",
     "../browser_proxy:browser_proxy",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
index c5ad4cc..559c687 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
@@ -2,32 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
+import {DeviceOperator} from './device_operator.js';
 
 /**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for mojo.
- */
-cca.mojo = cca.mojo || {};
-
-/**
- * Type definition for cca.mojo.PhotoCapabilities.
+ * Extended PhotoCapabilities type used by Chrome OS HAL3 VCD.
  * @extends {PhotoCapabilities}
  * @record
  */
-cca.mojo.PhotoCapabilities = function() {};
+const CrosPhotoCapabilities = function() {};
 
-/** @type {Array<string>} */
-cca.mojo.PhotoCapabilities.prototype.supportedEffects;
+/** @type {!Array<string>} */
+CrosPhotoCapabilities.prototype.supportedEffects;
 
 /**
  * Creates the wrapper of JS image-capture and Mojo image-capture.
  */
-cca.mojo.ImageCapture = class {
+export class CrosImageCapture {
   /**
    * @param {!MediaStreamTrack} videoTrack A video track whose still images will
    *     be taken.
@@ -50,11 +40,11 @@
 
   /**
    * Gets the photo capabilities with the available options/effects.
-   * @return {!Promise<!PhotoCapabilities|cca.mojo.PhotoCapabilities>} Promise
+   * @return {!Promise<!PhotoCapabilities|CrosPhotoCapabilities>} Promise
    *     for the result.
    */
   async getPhotoCapabilities() {
-    const deviceOperator = await cca.mojo.DeviceOperator.getInstance();
+    const deviceOperator = await DeviceOperator.getInstance();
     if (!deviceOperator) {
       return this.capture_.getPhotoCapabilities();
     }
@@ -67,8 +57,8 @@
     }
     const baseCapabilities = await this.capture_.getPhotoCapabilities();
 
-    let /** !cca.mojo.PhotoCapabilities */ extendedCapabilities;
-    Object.assign(extendedCapabilities, baseCapabilities, {supportedEffects});
+    const extendedCapabilities = /** @type{!CrosPhotoCapabilities} */ (
+        Object.assign({}, baseCapabilities, {supportedEffects}));
     return extendedCapabilities;
   }
 
@@ -88,7 +78,7 @@
   async takePhoto(photoSettings, photoEffects = []) {
     /** @type {Array<!Promise<!Blob>>} */
     const takes = [];
-    const deviceOperator = await cca.mojo.DeviceOperator.getInstance();
+    const deviceOperator = await DeviceOperator.getInstance();
     if (deviceOperator === null && photoEffects.length > 0) {
       throw new Error('Applying effects is not supported on this device');
     }
@@ -122,4 +112,7 @@
       return takes;
     }
   }
-};
+}
+
+/** @const */
+cca.mojo.ImageCapture = CrosImageCapture;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/namespace.js b/chrome/browser/resources/chromeos/camera/src/js/namespace.js
index dbd58c3..fe9c406f 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/namespace.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/namespace.js
@@ -11,6 +11,7 @@
 var cca = {
   device: {},
   intent: {},
+  metrics: {},
   models: {
     FileSystem: {},
   },
@@ -24,6 +25,8 @@
   tooltip: {},
   util: {},
   views: {
-    camera: {},
+    camera: {
+      timertick: {},
+    },
   },
 };
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
index f8c2f82..8a7c0ce 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -159,16 +159,46 @@
     });
     chrome.app.window.current().onMinimized.addListener(() => this.start());
 
+    document.addEventListener('visibilitychange', async () => {
+      const isTabletBackground = await this.isTabletBackground_();
+      const recording = cca.state.get(cca.state.State.TAKING) &&
+          cca.state.get(cca.Mode.VIDEO);
+      if (isTabletBackground && !recording) {
+        this.start();
+      }
+    });
+
     this.configuring_ = null;
   }
 
   /**
-   * Whether app window is suspended.
-   * @return {boolean}
+   * @return {boolean} Returns if window is fully overlapped by other window in
+   * both window mode or tablet mode.
+   * @private
    */
-  get suspended() {
+  get isVisible_() {
+    return document.visibilityState !== 'hidden';
+  }
+
+  /**
+   * @return {!Promise<boolean>} Resolved to boolean value indicating whether
+   * window is put to background in tablet mode.
+   * @private
+   */
+  async isTabletBackground_() {
+    const isTabletMode =
+        await cca.mojo.ChromeHelper.getInstance().isTabletMode();
+    return isTabletMode && !this.isVisible_;
+  }
+
+  /**
+   * Whether app window is suspended.
+   * @return {!Promise<boolean>}
+   */
+  async isSuspended() {
     return this.locked_ || chrome.app.window.current().isMinimized() ||
-        cca.state.get(cca.state.State.SUSPEND);
+        cca.state.get(cca.state.State.SUSPEND) ||
+        await this.isTabletBackground_();
   }
 
   /**
@@ -335,7 +365,7 @@
     }
     for (const {resolution: captureR, previewCandidates} of resolCandidates) {
       for (const constraints of previewCandidates) {
-        if (this.suspended) {
+        if (await this.isSuspended()) {
           throw new cca.views.CameraSuspendedError();
         }
         try {
@@ -389,7 +419,7 @@
   async start_() {
     try {
       await this.infoUpdater_.lockDeviceInfo(async () => {
-        if (!this.suspended) {
+        if (!await this.isSuspended()) {
           for (const id of await this.options_.videoDeviceIds()) {
             if (await this.startWithDevice_(id)) {
               // Make the different active camera announced by screen reader.
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
index bfdabac..75099fd 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
@@ -2,34 +2,38 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for views.
- */
-cca.views = cca.views || {};
-
-/**
- * Namespace for Camera view.
- */
-cca.views.camera = cca.views.camera || {};
-
-/* eslint-disable no-unused-vars */
+import {assert, assertInstanceof} from '../../chrome_util.js';
+import {CaptureCandidate,           // eslint-disable-line no-unused-vars
+        ConstraintsPreferrer,       // eslint-disable-line no-unused-vars
+        PhotoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
+        VideoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
+} from '../../device/constraints_preferrer.js';
+import {Filenamer} from '../../models/filenamer.js';
+import * as filesystem from '../../models/filesystem.js';
+// eslint-disable-next-line no-unused-vars
+import {VideoSaver} from '../../models/video_saver_interface.js';
+import {DeviceOperator, parseMetadata} from '../../mojo/device_operator.js';
+import {CrosImageCapture} from '../../mojo/image_capture.js';
+import {PerfEvent} from '../../perf.js';
+import * as sound from '../../sound.js';
+import * as state from '../../state.js';
+import * as toast from '../../toast.js';
+import {Resolution,
+        ResolutionList,  // eslint-disable-line no-unused-vars
+} from '../../type.js';
+import {Mode} from '../../type.js';
+import * as util from '../../util.js';
+import {RecordTime} from './recordtime.js';
 
 /**
  * Contains video recording result.
  * @typedef {{
  *     resolution: {width: number, height: number},
  *     duration: number,
- *     videoSaver: !cca.models.VideoSaver,
+ *     videoSaver: !VideoSaver,
  * }}
  */
-cca.views.camera.VideoResult;
+export let VideoResult;
 
 /**
  * Contains photo taking result.
@@ -38,55 +42,55 @@
  *     blob: !Blob,
  * }}
  */
-cca.views.camera.PhotoResult;
+export let PhotoResult;
 
 /**
  * Callback to trigger mode switching.
  * return {!Promise}
  * @typedef {function(): !Promise}
  */
-cca.views.camera.DoSwitchMode;
+export let DoSwitchMode;
 
 /**
  * Callback for saving photo capture result.
- * param {!cca.views.camera.PhotoResult} Captured photo result.
+ * param {!PhotoResult} Captured photo result.
  * param {string} Name of the photo result to be saved as.
  * return {!Promise}
- * @typedef {function(cca.views.camera.PhotoResult, string): !Promise}
+ * @typedef {function(PhotoResult, string): !Promise}
  */
-cca.views.camera.DoSavePhoto;
+export let DoSavePhoto;
 
 /**
  * Callback for allocating VideoSaver to save video capture result.
- * @typedef {function(): !Promise<!cca.models.VideoSaver>}
+ * @typedef {function(): !Promise<!VideoSaver>}
  */
-cca.views.camera.CreateVideoSaver;
+export let CreateVideoSaver;
 
 /**
  * Callback for saving video capture result.
- * param {!cca.views.camera.VideoResult} Captured video result.
+ * param {!VideoResult} Captured video result.
  * param {string} Name of the video result to be saved as.
  * return {!Promise}
- * @typedef {function(!cca.views.camera.VideoResult, string): !Promise}
+ * @typedef {function(!VideoResult, string): !Promise}
  */
-cca.views.camera.DoSaveVideo;
+export let DoSaveVideo;
 
 /**
  * Callback for playing shutter effect.
  * @typedef {function()}
  */
-cca.views.camera.PlayShutterEffect;
+export let PlayShutterEffect;
 
-/* eslint-enable no-unused-vars */
+/* eslint-disable no-unused-vars */
 
 /**
  * The abstract interface for the mode configuration.
  * @interface
  */
-cca.views.camera.ModeConfig = class {
+class ModeConfig {
   /**
    * Factory function to create capture object for this mode.
-   * @return {!cca.views.camera.ModeBase}
+   * @return {!ModeBase}
    * @abstract
    */
   captureFactory() {}
@@ -111,14 +115,14 @@
 
   /**
    * HALv3 constraints preferrer for this mode.
-   * @return {!cca.device.ConstraintsPreferrer}
+   * @return {!ConstraintsPreferrer}
    * @abstract
    */
   get constraintsPreferrer() {}
 
   /**
    * Mode to be fallbacked to when fail to configure this mode.
-   * @return {!cca.Mode}
+   * @return {!Mode}
    * @abstract
    */
   get nextMode() {}
@@ -131,34 +135,36 @@
   get captureIntent() {}
 
   /* eslint-enable getter-return */
-};
+}
+
+/* eslint-enable no-unused-vars */
 
 /**
  * Mode controller managing capture sequence of different camera mode.
  */
-cca.views.camera.Modes = class {
+export class Modes {
   /**
-   * @param {!cca.Mode} defaultMode Default mode to be switched to.
-   * @param {!cca.device.PhotoConstraintsPreferrer} photoPreferrer
-   * @param {!cca.device.VideoConstraintsPreferrer} videoPreferrer
-   * @param {!cca.views.camera.DoSwitchMode} doSwitchMode
-   * @param {!cca.views.camera.DoSavePhoto} doSavePhoto
-   * @param {!cca.views.camera.CreateVideoSaver} createVideoSaver
-   * @param {!cca.views.camera.DoSaveVideo} doSaveVideo
-   * @param {!cca.views.camera.PlayShutterEffect} playShutterEffect
+   * @param {!Mode} defaultMode Default mode to be switched to.
+   * @param {!PhotoConstraintsPreferrer} photoPreferrer
+   * @param {!VideoConstraintsPreferrer} videoPreferrer
+   * @param {!DoSwitchMode} doSwitchMode
+   * @param {!DoSavePhoto} doSavePhoto
+   * @param {!CreateVideoSaver} createVideoSaver
+   * @param {!DoSaveVideo} doSaveVideo
+   * @param {!PlayShutterEffect} playShutterEffect
    */
   constructor(
       defaultMode, photoPreferrer, videoPreferrer, doSwitchMode, doSavePhoto,
       createVideoSaver, doSaveVideo, playShutterEffect) {
     /**
-     * @type {!cca.views.camera.DoSwitchMode}
+     * @type {!DoSwitchMode}
      * @private
      */
     this.doSwitchMode_ = doSwitchMode;
 
     /**
      * Capture controller of current camera mode.
-     * @type {?cca.views.camera.ModeBase}
+     * @type {?ModeBase}
      */
     this.current = null;
 
@@ -174,10 +180,10 @@
      * @private
      */
     this.modesGroup_ =
-        /** @type {!HTMLElement} */ (document.querySelector('#modes-group'));
+        assertInstanceof(document.querySelector('#modes-group'), HTMLElement);
 
     /**
-     * @type {?cca.Resolution}
+     * @type {?Resolution}
      * @private
      */
     this.captureResolution_ = null;
@@ -190,7 +196,7 @@
      *     constraints-candidates.
      */
     const getV1Constraints = async function(videoMode, deviceId) {
-      const defaultFacing = await cca.util.getDefaultFacing();
+      const defaultFacing = await util.getDefaultFacing();
       return [
         {
           aspectRatio: {ideal: videoMode ? 1.7777777778 : 1.3333333333},
@@ -201,7 +207,7 @@
           width: {min: 640},
           frameRate: {min: 24},
         },
-      ].map((constraint) => {
+      ].map((/** !MediaTrackConstraints */ constraint) => {
         if (deviceId) {
           constraint.deviceId = {exact: deviceId};
         } else {
@@ -219,49 +225,49 @@
 
     /**
      * Mode classname and related functions and attributes.
-     * @type {!Object<!cca.Mode, !cca.views.camera.ModeConfig>}
+     * @type {!Object<!Mode, !ModeConfig>}
      * @private
      */
     this.allModes_ = {
-      [cca.Mode.VIDEO]: {
-        captureFactory: () => new cca.views.camera.Video(
-            /** @type {!MediaStream} */ (this.stream_), createVideoSaver,
+      [Mode.VIDEO]: {
+        captureFactory: () => new Video(
+            assertInstanceof(this.stream_, MediaStream), createVideoSaver,
             doSaveVideo),
         isSupported: async () => true,
         constraintsPreferrer: videoPreferrer,
         getV1Constraints: getV1Constraints.bind(this, true),
-        nextMode: cca.Mode.PHOTO,
+        nextMode: Mode.PHOTO,
         captureIntent: cros.mojom.CaptureIntent.VIDEO_RECORD,
       },
-      [cca.Mode.PHOTO]: {
-        captureFactory: () => new cca.views.camera.Photo(
-            /** @type {!MediaStream} */ (this.stream_), doSavePhoto,
+      [Mode.PHOTO]: {
+        captureFactory: () => new Photo(
+            assertInstanceof(this.stream_, MediaStream), doSavePhoto,
             this.captureResolution_, playShutterEffect),
         isSupported: async () => true,
         constraintsPreferrer: photoPreferrer,
         getV1Constraints: getV1Constraints.bind(this, false),
-        nextMode: cca.Mode.SQUARE,
+        nextMode: Mode.SQUARE,
         captureIntent: cros.mojom.CaptureIntent.STILL_CAPTURE,
       },
-      [cca.Mode.SQUARE]: {
-        captureFactory: () => new cca.views.camera.Square(
-            /** @type {!MediaStream} */ (this.stream_), doSavePhoto,
+      [Mode.SQUARE]: {
+        captureFactory: () => new Square(
+            assertInstanceof(this.stream_, MediaStream), doSavePhoto,
             this.captureResolution_, playShutterEffect),
         isSupported: async () => true,
         constraintsPreferrer: photoPreferrer,
         getV1Constraints: getV1Constraints.bind(this, false),
-        nextMode: cca.Mode.PHOTO,
+        nextMode: Mode.PHOTO,
         captureIntent: cros.mojom.CaptureIntent.STILL_CAPTURE,
       },
-      [cca.Mode.PORTRAIT]: {
-        captureFactory: () => new cca.views.camera.Portrait(
-            /** @type {!MediaStream} */ (this.stream_), doSavePhoto,
+      [Mode.PORTRAIT]: {
+        captureFactory: () => new Portrait(
+            assertInstanceof(this.stream_, MediaStream), doSavePhoto,
             this.captureResolution_, playShutterEffect),
         isSupported: async (deviceId) => {
           if (deviceId === null) {
             return false;
           }
-          const deviceOperator = await cca.mojo.DeviceOperator.getInstance();
+          const deviceOperator = await DeviceOperator.getInstance();
           if (deviceOperator === null) {
             return false;
           }
@@ -269,40 +275,40 @@
         },
         constraintsPreferrer: photoPreferrer,
         getV1Constraints: getV1Constraints.bind(this, false),
-        nextMode: cca.Mode.PHOTO,
+        nextMode: Mode.PHOTO,
         captureIntent: cros.mojom.CaptureIntent.STILL_CAPTURE,
       },
     };
 
     document.querySelectorAll('.mode-item>input').forEach((element) => {
       element.addEventListener('click', (event) => {
-        if (!cca.state.get(cca.state.State.STREAMING) ||
-            cca.state.get(cca.state.State.TAKING)) {
+        if (!state.get(state.State.STREAMING) ||
+            state.get(state.State.TAKING)) {
           event.preventDefault();
         }
       });
       element.addEventListener('change', async (event) => {
         if (element.checked) {
-          var mode = element.dataset.mode;
+          const mode = element.dataset.mode;
           this.updateModeUI_(mode);
-          cca.state.set(cca.state.State.MODE_SWITCHING, true);
+          state.set(state.State.MODE_SWITCHING, true);
           const isSuccess = await this.doSwitchMode_();
-          cca.state.set(
-              cca.state.State.MODE_SWITCHING, false, {hasError: !isSuccess});
+          state.set(state.State.MODE_SWITCHING, false, {hasError: !isSuccess});
         }
       });
     });
 
-    [cca.state.State.EXPERT, cca.state.State.SAVE_METADATA].forEach((state) => {
-      cca.state.addObserver(state, this.updateSaveMetadata_.bind(this));
-    });
+    [state.State.EXPERT, state.State.SAVE_METADATA].forEach(
+        (/** state.State */ s) => {
+          state.addObserver(s, this.updateSaveMetadata_.bind(this));
+        });
 
     // Set default mode when app started.
     this.updateModeUI_(defaultMode);
   }
 
   /**
-   * @return {!Array<cca.Mode>}
+   * @return {!Array<Mode>}
    * @private
    */
   get allModeNames_() {
@@ -311,11 +317,11 @@
 
   /**
    * Updates state of mode related UI to the target mode.
-   * @param {!cca.Mode} mode Mode to be toggled.
+   * @param {!Mode} mode Mode to be toggled.
    * @private
    */
   updateModeUI_(mode) {
-    this.allModeNames_.forEach((m) => cca.state.set(m, m === mode));
+    this.allModeNames_.forEach((m) => state.set(m, m === mode));
     const element =
         document.querySelector(`.mode-item>input[data-mode=${mode}]`);
     element.checked = true;
@@ -324,7 +330,7 @@
         wrapper.offsetHeight / 2;
     // Make photo mode scroll slightly upper so that the third mode item falls
     // in blur area: crbug.com/988869
-    if (mode === cca.Mode.PHOTO) {
+    if (mode === Mode.PHOTO) {
       scrollTop -= 16;
     }
     this.modesGroup_.scrollTo({
@@ -337,13 +343,13 @@
   /**
    * Gets all mode candidates. Desired trying sequence of candidate modes is
    * reflected in the order of the returned array.
-   * @return {!Array<!cca.Mode>} Mode candidates to be tried out.
+   * @return {!Array<!Mode>} Mode candidates to be tried out.
    */
   getModeCandidates() {
     const tried = {};
-    const results = [];
-    let mode = this.allModeNames_.find(cca.state.get);
-    cca.assert(mode !== undefined);
+    const /** !Array<Mode> */ results = [];
+    let mode = this.allModeNames_.find(state.get);
+    assert(mode !== undefined);
     while (!tried[mode]) {
       tried[mode] = true;
       results.push(mode);
@@ -355,10 +361,10 @@
   /**
    * Gets all available capture resolution and its corresponding preview
    * constraints for the given mode.
-   * @param {!cca.Mode} mode
+   * @param {!Mode} mode
    * @param {string} deviceId
-   * @param {!cca.ResolutionList} previewResolutions
-   * @return {!Array<!cca.CaptureCandidate>}
+   * @param {!ResolutionList} previewResolutions
+   * @return {!Array<!CaptureCandidate>}
    */
   getResolutionCandidates(mode, deviceId, previewResolutions) {
     return this.allModes_[mode].constraintsPreferrer.getSortedCandidates(
@@ -368,9 +374,9 @@
   /**
    * Gets capture resolution and its corresponding preview constraints for the
    * given mode on camera HALv1 device.
-   * @param {!cca.Mode} mode
+   * @param {!Mode} mode
    * @param {?string} deviceId
-   * @return {!Promise<!Array<!cca.CaptureCandidate>>}
+   * @return {!Promise<!Array<!CaptureCandidate>>}
    */
   async getResolutionCandidatesV1(mode, deviceId) {
     const previewCandidates =
@@ -380,7 +386,7 @@
 
   /**
    * Gets capture intent for the given mode.
-   * @param {!cca.Mode} mode
+   * @param {!Mode} mode
    * @return {cros.mojom.CaptureIntent} Capture intent for the given mode.
    */
   getCaptureIntent(mode) {
@@ -390,12 +396,13 @@
   /**
    * Gets supported modes for video device of given device id.
    * @param {?string} deviceId Device id of the video device.
-   * @return {!Promise<!Array<!cca.Mode>>} All supported mode for
+   * @return {!Promise<!Array<!Mode>>} All supported mode for
    *     the video device.
    */
   async getSupportedModes(deviceId) {
-    let supportedModes = [];
-    for (const [mode, obj] of Object.entries(this.allModes_)) {
+    const /** !Array<Mode> */ supportedModes = [];
+    for (const mode of this.allModeNames_) {
+      const obj = this.allModes_[mode];
       if (await obj.isSupported(deviceId)) {
         supportedModes.push(mode);
       }
@@ -421,10 +428,10 @@
 
   /**
    * Creates and updates new current mode object.
-   * @param {!cca.Mode} mode Classname of mode to be updated.
+   * @param {!Mode} mode Classname of mode to be updated.
    * @param {!MediaStream} stream Stream of the new switching mode.
    * @param {?string} deviceId Device id of currently working video device.
-   * @param {?cca.Resolution} captureResolution Capturing resolution width and
+   * @param {?Resolution} captureResolution Capturing resolution width and
    *     height.
    * @return {!Promise}
    */
@@ -449,8 +456,7 @@
    * @private
    */
   async updateSaveMetadata_() {
-    if (cca.state.get(cca.state.State.EXPERT) &&
-        cca.state.get(cca.state.State.SAVE_METADATA)) {
+    if (state.get(state.State.EXPERT) && state.get(state.State.SAVE_METADATA)) {
       await this.enableSaveMetadata_();
     } else {
       await this.disableSaveMetadata_();
@@ -478,16 +484,16 @@
       await this.current.removeMetadataObserver();
     }
   }
-};
+}
 
 /**
  * Base class for controlling capture sequence in different camera modes.
  * @abstract
  */
-cca.views.camera.ModeBase = class {
+class ModeBase {
   /**
    * @param {!MediaStream} stream
-   * @param {?cca.Resolution} captureResolution Capturing resolution width and
+   * @param {?Resolution} captureResolution Capturing resolution width and
    *     height.
    */
   constructor(stream, captureResolution) {
@@ -501,7 +507,7 @@
     /**
      * Capture resolution. May be null on device not support of setting
      * resolution.
-     * @type {?cca.Resolution}
+     * @type {?Resolution}
      * @private
      */
     this.captureResolution_ = captureResolution;
@@ -559,30 +565,34 @@
    * @protected
    */
   stop_() {}
-};
+}
+
+/**
+ * Video recording MIME type. Mkv with AVC1 is the only preferred format.
+ * @type {string}
+ */
+const VIDEO_MIMETYPE = 'video/x-matroska;codecs=avc1';
 
 /**
  * Video mode capture controller.
- * @constructor
- * @extends {cca.views.camera.ModeBase}
  */
-cca.views.camera.Video = class extends cca.views.camera.ModeBase {
+class Video extends ModeBase {
   /**
    * @param {!MediaStream} stream
-   * @param {!cca.views.camera.CreateVideoSaver} createVideoSaver
-   * @param {!cca.views.camera.DoSaveVideo} doSaveVideo
+   * @param {!CreateVideoSaver} createVideoSaver
+   * @param {!DoSaveVideo} doSaveVideo
    */
   constructor(stream, createVideoSaver, doSaveVideo) {
     super(stream, null);
 
     /**
-     * @type {!cca.views.camera.CreateVideoSaver}
+     * @type {!CreateVideoSaver}
      * @private
      */
     this.createVideoSaver_ = createVideoSaver;
 
     /**
-     * @type {!cca.views.camera.DoSaveVideo}
+     * @type {!DoSaveVideo}
      * @private
      */
     this.doSaveVideo_ = doSaveVideo;
@@ -603,17 +613,17 @@
 
     /**
      * Record-time for the elapsed recording time.
-     * @type {!cca.views.camera.RecordTime}
+     * @type {!RecordTime}
      * @private
      */
-    this.recordTime_ = new cca.views.camera.RecordTime();
+    this.recordTime_ = new RecordTime();
   }
 
   /**
    * @override
    */
   async start_() {
-    this.startSound_ = cca.sound.play('#sound-rec-start');
+    this.startSound_ = sound.play('#sound-rec-start');
     try {
       await this.startSound_;
     } finally {
@@ -622,43 +632,40 @@
 
     if (this.mediaRecorder_ === null) {
       try {
-        if (!MediaRecorder.isTypeSupported(
-                cca.views.camera.Video.VIDEO_MIMETYPE)) {
+        if (!MediaRecorder.isTypeSupported(VIDEO_MIMETYPE)) {
           throw new Error('The preferred mimeType is not supported.');
         }
-        this.mediaRecorder_ = new MediaRecorder(
-            this.stream_, {mimeType: cca.views.camera.Video.VIDEO_MIMETYPE});
+        this.mediaRecorder_ =
+            new MediaRecorder(this.stream_, {mimeType: VIDEO_MIMETYPE});
       } catch (e) {
-        cca.toast.show('error_msg_record_start_failed');
+        toast.show('error_msg_record_start_failed');
         throw e;
       }
     }
 
     this.recordTime_.start();
+    let /** ?VideoSaver */ videoSaver = null;
+    let /** number */ duration = 0;
     try {
-      var videoSaver = await this.captureVideo_();
+      videoSaver = await this.captureVideo_();
     } catch (e) {
-      cca.toast.show('error_msg_empty_recording');
+      toast.show('error_msg_empty_recording');
       throw e;
     } finally {
-      var duration = this.recordTime_.stop();
+      duration = this.recordTime_.stop();
     }
-    cca.sound.play('#sound-rec-end');
+    sound.play('#sound-rec-end');
 
     const settings = this.stream_.getVideoTracks()[0].getSettings();
-    const resolution = new cca.Resolution(settings.width, settings.height);
-    cca.state.set(cca.perf.PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, true);
+    const resolution = new Resolution(settings.width, settings.height);
+    state.set(PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, true);
     try {
       await this.doSaveVideo_(
-          {resolution, duration, videoSaver},
-          (new cca.models.Filenamer()).newVideoName());
-      cca.state.set(
-          cca.perf.PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, false,
-          {resolution});
+          {resolution, duration, videoSaver}, (new Filenamer()).newVideoName());
+      state.set(PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, false, {resolution});
     } catch (e) {
-      cca.state.set(
-          cca.perf.PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, false,
-          {hasError: true});
+      state.set(
+          PerfEvent.VIDEO_CAPTURE_POST_PROCESSING, false, {hasError: true});
       throw e;
     }
   }
@@ -678,7 +685,7 @@
   /**
    * Starts recording and waits for stop recording event triggered by stop
    * shutter.
-   * @return {!Promise<!cca.models.VideoSaver>} Saves recorded video.
+   * @return {!Promise<!VideoSaver>} Saves recorded video.
    * @private
    */
   async captureVideo_() {
@@ -687,13 +694,13 @@
     return new Promise((resolve, reject) => {
       let noChunk = true;
 
-      var ondataavailable = (event) => {
+      const ondataavailable = (event) => {
         if (event.data && event.data.size > 0) {
           noChunk = false;
           saver.write(event.data);
         }
       };
-      var onstop = (event) => {
+      const onstop = (event) => {
         this.mediaRecorder_.removeEventListener(
             'dataavailable', ondataavailable);
         this.mediaRecorder_.removeEventListener('stop', onstop);
@@ -710,39 +717,31 @@
       this.mediaRecorder_.start(3000);
     });
   }
-};
-
-/**
- * Video recording MIME type. Mkv with AVC1 is the only preferred
- * format.
- * @type {string}
- * @const
- */
-cca.views.camera.Video.VIDEO_MIMETYPE = 'video/x-matroska;codecs=avc1';
+}
 
 /**
  * Photo mode capture controller.
  */
-cca.views.camera.Photo = class extends cca.views.camera.ModeBase {
+class Photo extends ModeBase {
   /**
    * @param {!MediaStream} stream
-   * @param {!cca.views.camera.DoSavePhoto} doSavePhoto
-   * @param {?cca.Resolution} captureResolution
-   * @param {!cca.views.camera.PlayShutterEffect} playShutterEffect
+   * @param {!DoSavePhoto} doSavePhoto
+   * @param {?Resolution} captureResolution
+   * @param {!PlayShutterEffect} playShutterEffect
    */
   constructor(stream, doSavePhoto, captureResolution, playShutterEffect) {
     super(stream, captureResolution);
 
     /**
      * Callback for saving picture.
-     * @type {!cca.views.camera.DoSavePhoto}
+     * @type {!DoSavePhoto}
      * @protected
      */
     this.doSavePhoto_ = doSavePhoto;
 
     /**
-     * ImageCapture object to capture still photos.
-     * @type {?cca.mojo.ImageCapture}
+     * CrosImageCapture object to capture still photos.
+     * @type {?CrosImageCapture}
      * @private
      */
     this.crosImageCapture_ = null;
@@ -763,7 +762,7 @@
 
     /**
      * Callback for playing shutter effect.
-     * @type {!cca.views.camera.PlayShutterEffect}
+     * @type {!PlayShutterEffect}
      * @protected
      */
     this.playShutterEffect_ = playShutterEffect;
@@ -775,7 +774,7 @@
   async start_() {
     if (this.crosImageCapture_ === null) {
       this.crosImageCapture_ =
-          new cca.mojo.ImageCapture(this.stream_.getVideoTracks()[0]);
+          new CrosImageCapture(this.stream_.getVideoTracks()[0]);
     }
 
     await this.takePhoto_();
@@ -787,9 +786,9 @@
    * @private
    */
   async takePhoto_() {
-    const imageName = (new cca.models.Filenamer()).newImageName();
+    const imageName = (new Filenamer()).newImageName();
     if (this.metadataObserverId_ !== null) {
-      this.metadataNames_.push(cca.models.Filenamer.getMetadataName(imageName));
+      this.metadataNames_.push(Filenamer.getMetadataName(imageName));
     }
 
     let photoSettings;
@@ -810,19 +809,16 @@
       const results = await this.crosImageCapture_.takePhoto(photoSettings);
       this.playShutterEffect_();
 
-      cca.state.set(cca.perf.PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, true);
+      state.set(PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, true);
       const blob = await results[0];
-      const image = await cca.util.blobToImage(blob);
-      const resolution = new cca.Resolution(image.width, image.height);
+      const image = await util.blobToImage(blob);
+      const resolution = new Resolution(image.width, image.height);
       await this.doSavePhoto_({resolution, blob}, imageName);
-      cca.state.set(
-          cca.perf.PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, false,
-          {resolution});
+      state.set(PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, false, {resolution});
     } catch (e) {
-      cca.state.set(
-          cca.perf.PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, false,
-          {hasError: true});
-      cca.toast.show('error_msg_take_photo_failed');
+      state.set(
+          PerfEvent.PHOTO_CAPTURE_POST_PROCESSING, false, {hasError: true});
+      toast.show('error_msg_take_photo_failed');
       throw e;
     }
   }
@@ -836,7 +832,7 @@
       return;
     }
 
-    const deviceOperator = await cca.mojo.DeviceOperator.getInstance();
+    const deviceOperator = await DeviceOperator.getInstance();
     if (!deviceOperator) {
       return;
     }
@@ -858,11 +854,11 @@
           continue;
         }
 
-        const val = cca.mojo.parseMetadata(entry);
+        const val = parseMetadata(entry);
         parsedMetadata[key] = val;
       }
 
-      cca.models.FileSystem.saveBlob(
+      filesystem.saveBlob(
           new Blob(
               [JSON.stringify(parsedMetadata, null, 2)],
               {type: 'application/json'}),
@@ -883,7 +879,7 @@
       return;
     }
 
-    const deviceOperator = await cca.mojo.DeviceOperator.getInstance();
+    const deviceOperator = await DeviceOperator.getInstance();
     if (!deviceOperator) {
       return;
     }
@@ -897,17 +893,17 @@
     }
     this.metadataObserverId_ = null;
   }
-};
+}
 
 /**
  * Square mode capture controller.
  */
-cca.views.camera.Square = class extends cca.views.camera.Photo {
+class Square extends Photo {
   /**
    * @param {!MediaStream} stream
-   * @param {!cca.views.camera.DoSavePhoto} doSavePhoto
-   * @param {?cca.Resolution} captureResolution
-   * @param {!cca.views.camera.PlayShutterEffect} playShutterEffect
+   * @param {!DoSavePhoto} doSavePhoto
+   * @param {?Resolution} captureResolution
+   * @param {!PlayShutterEffect} playShutterEffect
    */
   constructor(stream, doSavePhoto, captureResolution, playShutterEffect) {
     super(stream, doSavePhoto, captureResolution, playShutterEffect);
@@ -917,8 +913,7 @@
       // orientation information. Corrects the orientation before the square
       // cut.
       result.blob = await new Promise(
-          (resolve, reject) =>
-              cca.util.orientPhoto(result.blob, resolve, reject));
+          (resolve, reject) => util.orientPhoto(result.blob, resolve, reject));
       result.blob = await this.cropSquare(result.blob);
       await doSavePhoto(result, ...args);
     };
@@ -930,7 +925,7 @@
    * @return {!Promise<!Blob>} Promise with result cropped square image.
    */
   async cropSquare(blob) {
-    const img = await cca.util.blobToImage(blob);
+    const img = await util.blobToImage(blob);
     let side = Math.min(img.width, img.height);
     let canvas = document.createElement('canvas');
     canvas.width = side;
@@ -945,17 +940,17 @@
     croppedBlob.resolution = blob.resolution;
     return croppedBlob;
   }
-};
+}
 
 /**
  * Portrait mode capture controller.
  */
-cca.views.camera.Portrait = class extends cca.views.camera.Photo {
+class Portrait extends Photo {
   /**
    * @param {!MediaStream} stream
-   * @param {!cca.views.camera.DoSavePhoto} doSavePhoto
-   * @param {?cca.Resolution} captureResolution
-   * @param {!cca.views.camera.PlayShutterEffect} playShutterEffect
+   * @param {!DoSavePhoto} doSavePhoto
+   * @param {?Resolution} captureResolution
+   * @param {!PlayShutterEffect} playShutterEffect
    */
   constructor(stream, doSavePhoto, captureResolution, playShutterEffect) {
     super(stream, doSavePhoto, captureResolution, playShutterEffect);
@@ -967,7 +962,7 @@
   async start_() {
     if (this.crosImageCapture_ === null) {
       this.crosImageCapture_ =
-          new cca.mojo.ImageCapture(this.stream_.getVideoTracks()[0]);
+          new CrosImageCapture(this.stream_.getVideoTracks()[0]);
     }
 
     let photoSettings;
@@ -984,46 +979,54 @@
       });
     }
 
-    const filenamer = new cca.models.Filenamer();
+    const filenamer = new Filenamer();
     const refImageName = filenamer.newBurstName(false);
     const portraitImageName = filenamer.newBurstName(true);
 
     if (this.metadataObserverId_ !== null) {
-      [refImageName, portraitImageName].forEach((imageName) => {
-        this.metadataNames_.push(
-            cca.models.Filenamer.getMetadataName(imageName));
+      [refImageName, portraitImageName].forEach((/** string */ imageName) => {
+        this.metadataNames_.push(Filenamer.getMetadataName(imageName));
       });
     }
 
+    let /** ?Promise<!Blob> */ reference;
+    let /** ?Promise<!Blob> */ portrait;
+
     try {
-      var [reference, portrait] = await this.crosImageCapture_.takePhoto(
+      [reference, portrait] = await this.crosImageCapture_.takePhoto(
           photoSettings, [cros.mojom.Effect.PORTRAIT_MODE]);
       this.playShutterEffect_();
     } catch (e) {
-      cca.toast.show('error_msg_take_photo_failed');
+      toast.show('error_msg_take_photo_failed');
       throw e;
     }
 
-    cca.state.set(
-        cca.perf.PerfEvent.PORTRAIT_MODE_CAPTURE_POST_PROCESSING, true);
+    state.set(PerfEvent.PORTRAIT_MODE_CAPTURE_POST_PROCESSING, true);
     let hasError = false;
-    const [refSave, portraitSave] = [
-      [reference, refImageName],
-      [portrait, portraitImageName],
-    ].map(async ([p, imageName]) => {
+
+    /**
+     * @param {!Promise<!Blob>} p
+     * @param {string} imageName
+     * @return {!Promise}
+     */
+    const saveResult = async (p, imageName) => {
       const isPortrait = Object.is(p, portrait);
+      let /** ?Blob */ blob = null;
       try {
-        var blob = await p;
+        blob = await p;
       } catch (e) {
         hasError = true;
-        cca.toast.show(
+        toast.show(
             isPortrait ? 'error_msg_take_portrait_photo_failed' :
                          'error_msg_take_photo_failed');
         throw e;
       }
-      const {width, height} = await cca.util.blobToImage(blob);
+      const {width, height} = await util.blobToImage(blob);
       await this.doSavePhoto_({resolution: {width, height}, blob}, imageName);
-    });
+    };
+
+    const refSave = saveResult(reference, refImageName);
+    const portraitSave = saveResult(portrait, portraitImageName);
     try {
       await portraitSave;
     } catch (e) {
@@ -1032,8 +1035,24 @@
       // TODO(inker): Log non-intended error.
     }
     await refSave;
-    cca.state.set(
-        cca.perf.PerfEvent.PORTRAIT_MODE_CAPTURE_POST_PROCESSING, false,
-        {hasError});
+    state.set(
+        PerfEvent.PORTRAIT_MODE_CAPTURE_POST_PROCESSING, false, {hasError});
   }
-};
+}
+
+/** @const */
+cca.views.camera.VideoResult = VideoResult;
+/** @const */
+cca.views.camera.PhotoResult = PhotoResult;
+/** @const */
+cca.views.camera.DoSwitchMode = DoSwitchMode;
+/** @const */
+cca.views.camera.DoSavePhoto = DoSavePhoto;
+/** @const */
+cca.views.camera.CreateVideoSaver = CreateVideoSaver;
+/** @const */
+cca.views.camera.DoSaveVideo = DoSaveVideo;
+/** @const */
+cca.views.camera.PlayShutterEffect = PlayShutterEffect;
+/** @const */
+cca.views.camera.Modes = Modes;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js
index 5e165a1..3d663766 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js
@@ -2,57 +2,40 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for views.
- */
-cca.views = cca.views || {};
-/**
- * Namespace for camera view.
- */
-cca.views.camera = cca.views.camera || {};
-
-/**
- * Namespace for timertick.
- */
-cca.views.camera.timertick = cca.views.camera.timertick || {};
+import {assertInstanceof} from '../../chrome_util.js';
+import {play} from '../../sound.js';
+import * as state from '../../state.js';
+import * as util from '../../util.js';
 
 /**
  * Handler to cancel the active running timer-ticks.
  * @type {?function()}
- * @private
  */
-cca.views.camera.timertick.cancel_ = null;
+let doCancel = null;
 
 /**
  * Starts timer ticking if applicable.
  * @return {!Promise} Promise for the operation.
  */
-cca.views.camera.timertick.start = function() {
-  cca.views.camera.timertick.cancel_ = null;
-  if (!cca.state.get(cca.state.State.TIMER)) {
+export function start() {
+  doCancel = null;
+  if (!state.get(state.State.TIMER)) {
     return Promise.resolve();
   }
   return new Promise((resolve, reject) => {
     let tickTimeout = null;
-    const tickMsg = cca.assertInstanceof(
+    const tickMsg = assertInstanceof(
         document.querySelector('#timer-tick-msg'), HTMLElement);
-    cca.views.camera.timertick.cancel_ = () => {
+    doCancel = () => {
       if (tickTimeout) {
         clearTimeout(tickTimeout);
         tickTimeout = null;
       }
-      cca.util.animateCancel(tickMsg);
+      util.animateCancel(tickMsg);
       reject(new Error('cancel'));
     };
 
-    let tickCounter = cca.state.get(cca.state.State.TIMER_10SEC) ? 10 : 3;
+    let tickCounter = state.get(state.State.TIMER_10SEC) ? 10 : 3;
     const sounds = {
       1: '#sound-tick-final',
       2: '#sound-tick-inc',
@@ -64,10 +47,10 @@
         resolve();
       } else {
         if (sounds[tickCounter] !== undefined) {
-          cca.sound.play(sounds[tickCounter]);
+          play(sounds[tickCounter]);
         }
         tickMsg.textContent = tickCounter + '';
-        cca.util.animateOnce(tickMsg);
+        util.animateOnce(tickMsg);
         tickTimeout = setTimeout(onTimerTick, 1000);
         tickCounter--;
       }
@@ -75,14 +58,19 @@
     // First tick immediately in the next message loop cycle.
     tickTimeout = setTimeout(onTimerTick, 0);
   });
-};
+}
 
 /**
  * Cancels active timer ticking if applicable.
  */
-cca.views.camera.timertick.cancel = function() {
-  if (cca.views.camera.timertick.cancel_) {
-    cca.views.camera.timertick.cancel_();
-    cca.views.camera.timertick.cancel_ = null;
+export function cancel() {
+  if (doCancel) {
+    doCancel();
+    doCancel = null;
   }
-};
+}
+
+/** @const */
+cca.views.camera.timertick.start = start;
+/** @const */
+cca.views.camera.timertick.cancel = cancel;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/dialog.js b/chrome/browser/resources/chromeos/camera/src/js/views/dialog.js
index 203bd89..a58bb44 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/dialog.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/dialog.js
@@ -2,24 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for views.
- */
-cca.views = cca.views || {};
+import {assertInstanceof, assertString} from '../chrome_util.js';
+import {View,
+        ViewName,  // eslint-disable-line no-unused-vars
+} from './view.js';
 
 /**
  * Creates the Dialog view controller.
  */
-cca.views.Dialog = class extends cca.views.View {
+export class Dialog extends View {
   /**
-   * @param {cca.views.ViewName} name View name of the dialog.
+   * @param {ViewName} name View name of the dialog.
    */
   constructor(name) {
     super(name, true);
@@ -28,21 +21,21 @@
      * @type {!HTMLButtonElement}
      * @private
      */
-    this.positiveButton_ = cca.assertInstanceof(
+    this.positiveButton_ = assertInstanceof(
         this.root.querySelector('.dialog-positive-button'), HTMLButtonElement);
 
     /**
      * @type {!HTMLButtonElement}
      * @private
      */
-    this.negativeButton_ = cca.assertInstanceof(
+    this.negativeButton_ = assertInstanceof(
         this.root.querySelector('.dialog-negative-button'), HTMLButtonElement);
 
     /**
      * @type {!HTMLElement}
      * @private
      */
-    this.messageHolder_ = cca.assertInstanceof(
+    this.messageHolder_ = assertInstanceof(
         this.root.querySelector('.dialog-msg-holder'), HTMLElement);
 
     this.positiveButton_.addEventListener('click', () => this.leave(true));
@@ -55,7 +48,7 @@
    * @override
    */
   entering({message, cancellable = false} = {}) {
-    message = cca.assertString(message);
+    message = assertString(message);
     this.messageHolder_.textContent = message;
     if (this.negativeButton_) {
       this.negativeButton_.hidden = !cancellable;
@@ -68,4 +61,7 @@
   focus() {
     this.positiveButton_.focus();
   }
-};
+}
+
+/** @const */
+cca.views.Dialog = Dialog;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/warning.js b/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
index 6dd131ba..aee8c7b 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
@@ -2,27 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for views.
- */
-cca.views = cca.views || {};
+import {assertString} from '../chrome_util.js';
+import {View, ViewName} from './view.js';
 
 /**
  * Creates the warning-view controller.
  */
-cca.views.Warning = class extends cca.views.View {
+export class Warning extends View {
   /**
    * @public
    */
   constructor() {
-    super(cca.views.ViewName.WARNING);
+    super(ViewName.WARNING);
 
     /**
      * @type {!Array<string>}
@@ -53,7 +44,7 @@
    * @override
    */
   entering(name) {
-    name = cca.assertString(name);
+    name = assertString(name);
 
     // Remove the error-name from the stack to avoid duplication. Then make the
     // error-name the latest one to show its message.
@@ -73,7 +64,7 @@
      * Recovered error-name for leaving the view.
      * @type {string}
      */
-    const name = cca.assertString(args[0]);
+    const name = assertString(args[0]);
 
     // Remove the recovered error from the stack but don't leave the view until
     // there is no error left in the stack.
@@ -88,4 +79,7 @@
     document.querySelector('#error-msg').textContent = '';
     return true;
   }
-};
+}
+
+/** @const */
+cca.views.Warning = Warning;
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
index 9152fee..5a6233f 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/main.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -15,7 +15,7 @@
     <script src="../js/google-analytics-bundle.js"></script>
     <script type="module" src="../js/type.js"></script>
     <script type="module" src="../js/perf.js"></script>
-    <script defer src="../js/metrics.js"></script>
+    <script type="module" src="../js/metrics.js"></script>
     <script type="module" src="../js/intent.js"></script>
     <script type="module" src="../js/util.js"></script>
     <script type="module" src="../js/toast.js"></script>
@@ -27,7 +27,7 @@
     <script type="module" src="../js/device/constraints_preferrer.js"></script>
     <script type="module" src="../js/device/device_info_updater.js"></script>
     <script type="module" src="../js/models/filenamer.js"></script>
-    <script defer src="../js/gallerybutton.js"></script>
+    <script type="module" src="../js/gallerybutton.js"></script>
     <script type="module" src="../js/models/filesystem.js"></script>
     <script type="module" src="../js/models/result_saver.js"></script>
     <script type="module" src="../js/models/video_saver_interface.js"></script>
@@ -45,7 +45,7 @@
     <script defer src="../js/mojo/camera_app_helper.mojom-lite.js"></script>
     <script type="module" src="../js/mojo/chrome_helper.js"></script>
     <script type="module" src="../js/mojo/device_operator.js"></script>
-    <script defer src="../js/mojo/image_capture.js"></script>
+    <script type="module" src="../js/mojo/image_capture.js"></script>
     <script type="module" src="../js/views/view.js"></script>
     <script defer src="../js/views/camera.js"></script>
     <script defer src="../js/views/camera_intent.js"></script>
@@ -54,11 +54,11 @@
     <script type="module" src="../js/views/camera/preview.js"></script>
     <script type="module" src="../js/views/camera/recordtime.js"></script>
     <script type="module" src="../js/views/camera/review_result.js"></script>
-    <script defer src="../js/views/camera/timertick.js"></script>
-    <script defer src="../js/views/camera/modes.js"></script>
-    <script defer src="../js/views/dialog.js"></script>
+    <script type="module" src="../js/views/camera/timertick.js"></script>
+    <script type="module" src="../js/views/camera/modes.js"></script>
+    <script type="module" src="../js/views/dialog.js"></script>
     <script type="module" src="../js/views/settings.js"></script>
-    <script defer src="../js/views/warning.js"></script>
+    <script type="module" src="../js/views/warning.js"></script>
     <script type="module" src="../js/nav.js"></script>
     <script defer src="../js/main.js"></script>
   </head>
diff --git a/chrome/browser/resources/chromeos/crostini_installer/app.html b/chrome/browser/resources/chromeos/crostini_installer/app.html
index eb57c95..d55eddf 100644
--- a/chrome/browser/resources/chromeos/crostini_installer/app.html
+++ b/chrome/browser/resources/chromeos/crostini_installer/app.html
@@ -67,7 +67,7 @@
     <!-- Message containers. Depending on the current state, only one of them
       is visible. -->
     <div id="prompt-message" hidden="[[!isState_(state_, State.PROMPT)]]">
-      <span>$i18n{promptMessage}</span>
+      <span>$i18n{promptMessage} </span>
       <a href="$i18n{learnMoreUrl}" target="_blank">$i18n{learnMore}</a>
     </div>
     <div id="installing-message"
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index ac3f851..d415f6d9 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -263,7 +263,10 @@
 }
 
 void ChromePasswordProtectionService::Init() {
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+// The following code is disabled on Android. RefreshTokenIsAvailable cannot be
+// used in unit tests, because it needs to interact with system accounts.
+// Considering avoid running it during unit tests. See: crbug.com/1009957.
+#if !defined(OS_ANDROID)
   // This code is shared by the normal ctor and testing ctor.
 
   sync_password_hash_ = GetSyncPasswordHashFromPrefs();
@@ -376,12 +379,15 @@
   if (web_contents->IsFullscreenForCurrentTab())
     web_contents->ExitFullscreen(true);
 
+// TODO(crbug.com/1036042): Enable password reuse warning on Android.
+#if !defined(OS_ANDROID)
   ShowPasswordReuseModalWarningDialog(
       web_contents, this, password_type,
       base::BindOnce(&ChromePasswordProtectionService::OnUserAction,
                      base::Unretained(this), web_contents, password_type,
                      outcome, verdict_type, verdict_token,
                      WarningUIType::MODAL_DIALOG));
+#endif  // !defined(OS_ANDROID)
 
   LogWarningAction(WarningUIType::MODAL_DIALOG, WarningAction::SHOWN,
                    password_type);
@@ -831,12 +837,15 @@
   for (auto& observer : observer_list_)
     observer.OnGaiaPasswordChanged();
 
+// Disabled on Android, because enterprise reporting extension is not supported.
+#if !defined(OS_ANDROID)
   // Only report if the current password changed is the primary account and it's
   // not a Gmail account or if the current password changed is a content area
   // account and it's not a Gmail account.
   if ((!is_other_gaia_password && !IsPrimaryAccountGmail()) ||
       (is_other_gaia_password && !IsOtherGaiaAccountGmail(username)))
     ReportPasswordChanged();
+#endif
 }
 
 GURL ChromePasswordProtectionService::GetEnterpriseChangePasswordURL() const {
@@ -1134,7 +1143,10 @@
           : GetSignedInNonSyncAccount(username_for_last_shown_warning()).email;
   return email.empty() ? std::string() : gaia::ExtractDomainName(email);
 }
+#endif
 
+// Disabled on Android, because enterprise reporting extension is not supported.
+#if !defined(OS_ANDROID)
 void ChromePasswordProtectionService::MaybeReportPasswordReuseDetected(
     content::WebContents* web_contents,
     const std::string& username,
@@ -1174,7 +1186,9 @@
         ->OnPolicySpecifiedPasswordChanged(GetAccountInfo().email);
   }
 }
+#endif
 
+#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
 bool ChromePasswordProtectionService::HasUnhandledEnterprisePasswordReuse(
     content::WebContents* web_contents) const {
   return web_contents_with_unhandled_enterprise_reuses_.find(web_contents) !=
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index 26df847..092cdec2 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -55,8 +55,9 @@
 using password_manager::metrics_util::PasswordType;
 using url::Origin;
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
-// Shows the platform-specific password reuse modal dialog.
+#if !defined(OS_ANDROID)
+// Shows the desktop platforms specific password reuse modal dialog.
+// Implemented in password_reuse_modal_warning_dialog.
 void ShowPasswordReuseModalWarningDialog(
     content::WebContents* web_contents,
     ChromePasswordProtectionService* service,
@@ -184,7 +185,11 @@
   // returns an empty string.
   std::string GetOrganizationName(
       ReusedPasswordAccountType password_type) const;
+#endif
 
+// The following functions are disabled on Android, because enterprise reporting
+// extension is not supported.
+#if !defined(OS_ANDROID)
   // If the browser is not incognito and the user is reusing their enterprise
   // password or is a GSuite user, triggers
   // safeBrowsingPrivate.OnPolicySpecifiedPasswordReuseDetected.
@@ -197,7 +202,9 @@
 
   // Triggers "safeBrowsingPrivate.OnPolicySpecifiedPasswordChanged" API.
   void ReportPasswordChanged() override;
+#endif
 
+#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
   // Returns true if there's any enterprise password reuses unhandled in
   // |web_contents|. "Unhandled" is defined as user hasn't clicked on
   // "Change Password" button in modal warning dialog.
@@ -432,6 +439,8 @@
   FRIEND_TEST_ALL_PREFIXES(
       ChromePasswordProtectionServiceTest,
       VerifyOnPolicySpecifiedPasswordReuseDetectedEventForPhishingReuse);
+  FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest,
+                           VerifyGetWarningDetailTextSavedDomains);
 
   // Gets prefs associated with |profile_|.
   PrefService* GetPrefs();
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index 40826eb..0632655 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -1217,7 +1217,16 @@
   std::vector<size_t> placeholder_offsets;
   EXPECT_EQ(warning_text, service_->GetWarningDetailText(reused_password_type,
                                                          &placeholder_offsets));
+  // GetWarningDetailText shouldCall GetWarningDetailTextForSavedPasswords, so
+  // we can check to see if the placeholder offset values are the same.
+  // Hardcoding the offset in the expected value cannot be done as it's
+  // different for different OS.
+  std::vector<size_t> expected_placeholder_offsets;
+  service_->GetWarningDetailTextForSavedPasswords(
+      &expected_placeholder_offsets);
+  EXPECT_EQ(expected_placeholder_offsets, placeholder_offsets);
 
+  placeholder_offsets.clear();
   domains.push_back("www.2.example.com");
   service_->set_saved_passwords_matching_domains(domains);
   warning_text = l10n_util::GetStringFUTF16(
@@ -1225,7 +1234,12 @@
       base::UTF8ToUTF16(domains[0]), base::UTF8ToUTF16(domains[1]));
   EXPECT_EQ(warning_text, service_->GetWarningDetailText(reused_password_type,
                                                          &placeholder_offsets));
+  expected_placeholder_offsets.clear();
+  service_->GetWarningDetailTextForSavedPasswords(
+      &expected_placeholder_offsets);
+  EXPECT_EQ(expected_placeholder_offsets, placeholder_offsets);
 
+  placeholder_offsets.clear();
   domains.push_back("www.3.example.com");
   service_->set_saved_passwords_matching_domains(domains);
   warning_text = l10n_util::GetStringFUTF16(
@@ -1234,8 +1248,13 @@
       base::UTF8ToUTF16(domains[2]));
   EXPECT_EQ(warning_text, service_->GetWarningDetailText(reused_password_type,
                                                          &placeholder_offsets));
+  expected_placeholder_offsets.clear();
+  service_->GetWarningDetailTextForSavedPasswords(
+      &expected_placeholder_offsets);
+  EXPECT_EQ(expected_placeholder_offsets, placeholder_offsets);
 
   // Default domains should be prioritzed over other domains.
+  placeholder_offsets.clear();
   domains.push_back("amazon.com");
   service_->set_saved_passwords_matching_domains(domains);
   warning_text = l10n_util::GetStringFUTF16(
@@ -1244,6 +1263,25 @@
       base::UTF8ToUTF16(domains[1]));
   EXPECT_EQ(warning_text, service_->GetWarningDetailText(reused_password_type,
                                                          &placeholder_offsets));
+  expected_placeholder_offsets.clear();
+  service_->GetWarningDetailTextForSavedPasswords(
+      &expected_placeholder_offsets);
+  EXPECT_EQ(expected_placeholder_offsets, placeholder_offsets);
+}
+
+TEST_F(ChromePasswordProtectionServiceTest,
+       VerifyGetPlaceholdersForSavedPasswordWarningText) {
+  std::vector<std::string> domains{"www.example.com"};
+  domains.push_back("www.2.example.com");
+  domains.push_back("www.3.example.com");
+  domains.push_back("amazon.com");
+  service_->set_saved_passwords_matching_domains(domains);
+  // Default domains should be prioritzed over other domains.
+  std::vector<base::string16> expected_placeholders{
+      base::UTF8ToUTF16("amazon.com"), base::UTF8ToUTF16(domains[0]),
+      base::UTF8ToUTF16(domains[1])};
+  EXPECT_EQ(expected_placeholders,
+            service_->GetPlaceholdersForSavedPasswordWarningText());
 }
 
 TEST_F(ChromePasswordProtectionServiceTest,
diff --git a/chrome/browser/signin/OWNERS b/chrome/browser/signin/OWNERS
index cc02260..a5c06f58 100644
--- a/chrome/browser/signin/OWNERS
+++ b/chrome/browser/signin/OWNERS
@@ -8,5 +8,7 @@
 per-file easy_unlock_*=tengs@chromium.org
 per-file easy_unlock_*=xiyuan@chromium.org
 
+per-file signin_profile_attributes_updater*=msalama@chromium.org
+
 # TEAM: chrome-signin@chromium.org
 # COMPONENT: Services>SignIn
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index b145bdf..1203336f 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -17,7 +17,6 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/core/browser/consistency_cookie_manager_base.h"
 #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
@@ -35,11 +34,6 @@
 #include "google_apis/gaia/google_service_auth_error.h"
 #endif
 
-#if defined(OS_ANDROID)
-#include "components/signin/core/browser/consistency_cookie_manager_android.h"
-#include "components/signin/core/browser/mice_account_reconcilor_delegate.h"
-#endif
-
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 #include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
 #endif
@@ -150,8 +144,6 @@
       new AccountReconcilor(identity_manager, signin_client,
                             CreateAccountReconcilorDelegate(profile));
   reconcilor->Initialize(true /* start_reconcile_if_tokens_available */);
-  reconcilor->SetConsistencyCookieManager(CreateConsistencyCookieManager(
-      identity_manager, signin_client, reconcilor));
   return reconcilor;
 }
 
@@ -186,9 +178,6 @@
           IdentityManagerFactory::GetForProfile(profile),
           chromeos::AccountManagerMigratorFactory::GetForBrowserContext(
               profile));
-#elif defined(OS_ANDROID)
-      if (base::FeatureList::IsEnabled(signin::kMiceFeature))
-        return std::make_unique<signin::MiceAccountReconcilorDelegate>();
 #endif
       return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
           IdentityManagerFactory::GetForProfile(profile));
@@ -210,17 +199,3 @@
   NOTREACHED();
   return nullptr;
 }
-
-std::unique_ptr<signin::ConsistencyCookieManagerBase>
-AccountReconcilorFactory::CreateConsistencyCookieManager(
-    signin::IdentityManager* identity_manager,
-    SigninClient* signin_client,
-    AccountReconcilor* account_reconcilor) const {
-#if defined(OS_ANDROID)
-  if (base::FeatureList::IsEnabled(signin::kMiceFeature)) {
-    return std::make_unique<signin::ConsistencyCookieManagerAndroid>(
-        identity_manager, signin_client, account_reconcilor);
-  }
-#endif
-  return nullptr;
-}
diff --git a/chrome/browser/signin/account_reconcilor_factory.h b/chrome/browser/signin/account_reconcilor_factory.h
index 2ad657b9..c3ce98b 100644
--- a/chrome/browser/signin/account_reconcilor_factory.h
+++ b/chrome/browser/signin/account_reconcilor_factory.h
@@ -16,7 +16,6 @@
 
 namespace signin {
 class AccountReconcilorDelegate;
-class ConsistencyCookieManagerBase;
 }
 
 class AccountReconcilor;
@@ -49,11 +48,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-
-  std::unique_ptr<signin::ConsistencyCookieManagerBase>
-  CreateConsistencyCookieManager(signin::IdentityManager* identity_manager,
-                                 SigninClient* signin_client,
-                                 AccountReconcilor* account_reconcilor) const;
 };
 
 #endif  // CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_FACTORY_H_
diff --git a/chrome/browser/signin/consistency_cookie_browsertest.cc b/chrome/browser/signin/consistency_cookie_browsertest.cc
deleted file mode 100644
index 02919856..0000000
--- a/chrome/browser/signin/consistency_cookie_browsertest.cc
+++ /dev/null
@@ -1,164 +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 "components/signin/core/browser/consistency_cookie_manager_base.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/run_loop.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/account_reconcilor_factory.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/signin/core/browser/consistency_cookie_manager_base.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "google_apis/gaia/gaia_switches.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "net/cookies/canonical_cookie.h"
-#include "net/test/embedded_test_server/default_handlers.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/network/public/mojom/cookie_manager.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace {
-
-const char kConsistencyCookieName[] = "CHROME_ID_CONSISTENCY_STATE";
-
-// Subclass of ConsistencyCookieManagerBase allowing to manually control the
-// value of the cookie.
-class TestConsistencyCookieManager
-    : public signin::ConsistencyCookieManagerBase,
-      public network::mojom::CookieChangeListener {
- public:
-  TestConsistencyCookieManager(SigninClient* client,
-                               AccountReconcilor* reconcilor)
-      : signin::ConsistencyCookieManagerBase(client, reconcilor) {
-    // Listen to cookie changes.
-    client->GetCookieManager()->AddGlobalChangeListener(
-        cookie_listener_receiver_.BindNewPipeAndPassRemote());
-    // Subclasses have to call UpdateCookie() in the constructor.
-    UpdateCookie();
-    // Wait for the initial cookie to be set.
-    WaitForCookieChange();
-  }
-
-  // Sets a new value for the consistency cookie.
-  void SetValue(const std::string& value) {
-    value_ = value;
-    UpdateCookie();
-    WaitForCookieChange();
-  }
-
- private:
-  // Waits until OnCookieChange is called.
-  void WaitForCookieChange() {
-    base::RunLoop loop;
-    run_loop_quit_closure_ = loop.QuitClosure();
-    loop.Run();
-  }
-
-  // CookieChangeListener:
-  void OnCookieChange(const net::CookieChangeInfo& change) override {
-    if (change.cookie.Name() != kConsistencyCookieName)
-      return;
-    if (!run_loop_quit_closure_.is_null())
-      std::move(run_loop_quit_closure_).Run();
-  }
-
-  // ConsistencyCookieManagerBase:
-  std::string CalculateCookieValue() override { return value_; }
-
-  std::string value_ = "initial_value";
-  mojo::Receiver<network::mojom::CookieChangeListener>
-      cookie_listener_receiver_{this};
-  base::OnceClosure run_loop_quit_closure_;
-};
-
-}  // namespace
-
-class ConsistencyCookieBrowserTest : public InProcessBrowserTest {
- public:
-  ConsistencyCookieBrowserTest()
-      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
-    net::test_server::RegisterDefaultHandlers(&https_server_);
-  }
-
-  ~ConsistencyCookieBrowserTest() override {}
-
-  // Updates the cookie through the consistency cookie manager and blocks until
-  // it completes.
-  void SetCookieValue(const std::string& cookie_value) {
-    consistency_cookie_manager_->SetValue(cookie_value);
-  }
-
-  // Checks the cookie both in HTTP and javascript.
-  void CheckCookieValue(const std::string& expected_cookie) {
-    // Check that the cookie is set in HTTP.
-    ui_test_utils::NavigateToURL(
-        browser(),
-        https_server_.GetURL(GaiaUrls::GetInstance()->gaia_url().host(),
-                             "/echoheader?Cookie"));
-    std::string http_cookie =
-        content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
-                        "document.body.innerText")
-            .ExtractString();
-    EXPECT_EQ(expected_cookie, http_cookie);
-
-    // Check that the cookie is available in javascript.
-    std::string javascript_cookie =
-        content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
-                        "document.cookie")
-            .ExtractString();
-    EXPECT_EQ(expected_cookie, javascript_cookie);
-  }
-
- private:
-  // InProcessBrowserTest:
-  void SetUp() override {
-    ASSERT_TRUE(https_server_.InitializeAndListen());
-    InProcessBrowserTest::SetUp();
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    const GURL& base_url = https_server_.base_url();
-    command_line->AppendSwitchASCII(switches::kGaiaUrl, base_url.spec());
-  }
-
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-    https_server_.StartAcceptingConnections();
-
-    // Setup the CookieConsistencyCookieManager
-    Profile* profile = browser()->profile();
-    AccountReconcilor* reconcilor =
-        AccountReconcilorFactory::GetForProfile(profile);
-    std::unique_ptr<TestConsistencyCookieManager> consistency_cookie_manager =
-        std::make_unique<TestConsistencyCookieManager>(
-            ChromeSigninClientFactory::GetForProfile(profile), reconcilor);
-    consistency_cookie_manager_ = consistency_cookie_manager.get();
-    reconcilor->SetConsistencyCookieManager(
-        std::move(consistency_cookie_manager));
-  }
-
-  net::EmbeddedTestServer https_server_;
-  TestConsistencyCookieManager* consistency_cookie_manager_;
-};
-
-// Tests that the ConsistencyCookieManager can set and change the cookie in HTTP
-// and javascript.
-IN_PROC_BROWSER_TEST_F(ConsistencyCookieBrowserTest, Basic) {
-  // Check the initial value.
-  CheckCookieValue(std::string(kConsistencyCookieName) + "=initial_value");
-  // Change the cookie.
-  SetCookieValue("new_value");
-  CheckCookieValue(std::string(kConsistencyCookieName) + "=new_value");
-}
diff --git a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
index 92a3af5..80d0d38 100644
--- a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
+++ b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
@@ -86,6 +86,19 @@
                                                reporting_info);
 }
 
+std::unique_ptr<ChromeMetricsHelper> CreateBadClockMetricsHelper(
+    content::WebContents* web_contents,
+    const GURL& request_url) {
+  // Set up the metrics helper for the BadClockUI.
+  security_interstitials::MetricsHelper::ReportDetails reporting_info;
+  reporting_info.metric_prefix = "bad_clock";
+  std::unique_ptr<ChromeMetricsHelper> metrics_helper =
+      std::make_unique<ChromeMetricsHelper>(web_contents, request_url,
+                                            reporting_info);
+  metrics_helper.get()->StartRecordingCaptivePortalMetrics(false);
+  return metrics_helper;
+}
+
 }  // namespace
 
 // static
@@ -173,6 +186,27 @@
 }
 
 // static
+BadClockBlockingPage*
+ChromeSecurityBlockingPageFactory::CreateBadClockBlockingPage(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    const base::Time& time_triggered,
+    ssl_errors::ClockState clock_state,
+    std::unique_ptr<SSLCertReporter> ssl_cert_reporter) {
+  auto page = std::make_unique<BadClockBlockingPage>(
+      web_contents, cert_error, ssl_info, request_url, time_triggered,
+      clock_state, std::move(ssl_cert_reporter),
+      std::make_unique<SSLErrorControllerClient>(
+          web_contents, ssl_info, cert_error, request_url,
+          CreateBadClockMetricsHelper(web_contents, request_url)));
+
+  ChromeSecurityBlockingPageFactory::DoChromeSpecificSetup(page.get());
+  return page.release();
+}
+
+// static
 void ChromeSecurityBlockingPageFactory::DoChromeSpecificSetup(
     SSLBlockingPageBase* page) {
   page->set_renderer_pref_callback(
diff --git a/chrome/browser/ssl/chrome_security_blocking_page_factory.h b/chrome/browser/ssl/chrome_security_blocking_page_factory.h
index 6a03629..c875e81 100644
--- a/chrome/browser/ssl/chrome_security_blocking_page_factory.h
+++ b/chrome/browser/ssl/chrome_security_blocking_page_factory.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_SSL_CHROME_SECURITY_BLOCKING_PAGE_FACTORY_H_
 
 #include "base/macros.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/ssl_blocking_page.h"
 #include "components/security_interstitials/content/ssl_blocking_page_base.h"
@@ -37,6 +38,17 @@
       const net::SSLInfo& ssl_info,
       int cert_error);
 
+  // Creates a bad clock blocking page. The caller is responsible for
+  // ownership of the returned object.
+  static BadClockBlockingPage* CreateBadClockBlockingPage(
+      content::WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      const base::Time& time_triggered,
+      ssl_errors::ClockState clock_state,
+      std::unique_ptr<SSLCertReporter> ssl_cert_reporter);
+
   // Does setup on |page| that is specific to the client (Chrome).
   static void DoChromeSpecificSetup(SSLBlockingPageBase* page);
 
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 214e887..3e43582 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -52,7 +52,6 @@
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ssl/bad_clock_blocking_page.h"
 #include "chrome/browser/ssl/cert_verifier_browser_test.h"
 #include "chrome/browser/ssl/certificate_reporting_test_utils.h"
 #include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
@@ -94,6 +93,7 @@
 #include "components/policy/policy_constants.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/cert_report_helper.h"
 #include "components/security_interstitials/content/security_interstitial_controller_client.h"
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index 4c892401..f72ba0dc 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/interstitials/enterprise_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ssl/bad_clock_blocking_page.h"
 #include "chrome/browser/ssl/blocked_interception_blocking_page.h"
 #include "chrome/browser/ssl/captive_portal_helper.h"
 #include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
@@ -36,6 +35,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/prefs/pref_service.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
 #include "components/security_interstitials/content/ssl_blocking_page.h"
@@ -543,9 +543,10 @@
     const base::Time& now,
     ssl_errors::ClockState clock_state) {
   // Show bad clock page. The interstitial owns the blocking page.
-  OnBlockingPageReady(new BadClockBlockingPage(
-      web_contents_, cert_error_, ssl_info_, request_url_, now, clock_state,
-      std::move(ssl_cert_reporter_)));
+  OnBlockingPageReady(
+      ChromeSecurityBlockingPageFactory::CreateBadClockBlockingPage(
+          web_contents_, cert_error_, ssl_info_, request_url_, now, clock_state,
+          std::move(ssl_cert_reporter_)));
 }
 
 void SSLErrorHandlerDelegateImpl::ShowBlockedInterceptionInterstitial() {
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 09307d4..6c8a7ed 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -261,11 +261,6 @@
       supervised_users::kSupervisedUserIframeFilter);
 }
 
-#if !defined(OS_ANDROID)
-void SupervisedUserService::InitSync(const std::string& refresh_token) {
-}
-#endif  // !defined(OS_ANDROID)
-
 void SupervisedUserService::AddObserver(
     SupervisedUserServiceObserver* observer) {
   observer_list_.AddObserver(observer);
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index 004b043b..f8938f4 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -139,12 +139,6 @@
 
   bool IsSupervisedUserIframeFilterEnabled() const;
 
-#if !defined(OS_ANDROID)
-  // Initializes this profile for syncing, using the provided |refresh_token| to
-  // mint access tokens for Sync.
-  void InitSync(const std::string& refresh_token);
-#endif
-
   void AddObserver(SupervisedUserServiceObserver* observer);
   void RemoveObserver(SupervisedUserServiceObserver* observer);
 
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
index 4fd146a..21008539 100644
--- a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
+++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
@@ -70,8 +70,9 @@
   return base::Optional<tab_groups::TabGroupId>();
 }
 
-tab_groups::TabGroupVisualData* AndroidLiveTabContext::GetVisualDataForGroup(
-    tab_groups::TabGroupId group) const {
+const tab_groups::TabGroupVisualData*
+AndroidLiveTabContext::GetVisualDataForGroup(
+    const tab_groups::TabGroupId& group) const {
   // Since we never return a group from GetTabGroupForTab(), this should never
   // be called.
   NOTREACHED();
@@ -79,8 +80,8 @@
 }
 
 void AndroidLiveTabContext::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData group_visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& group_visual_data) {
   // Not supported on Android.
 
   // TODO(crbug.com/1003128): ensure this never gets called (or remove
@@ -110,7 +111,7 @@
     int selected_navigation,
     const std::string& extension_app_id,
     base::Optional<tab_groups::TabGroupId> group,
-    const tab_groups::TabGroupVisualData group_visual_data,
+    const tab_groups::TabGroupVisualData& group_visual_data,
     bool select,
     bool pin,
     bool from_last_session,
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.h b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
index 5fac290..ffbc4af 100644
--- a/chrome/browser/ui/android/tab_model/android_live_tab_context.h
+++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
@@ -37,11 +37,11 @@
   bool IsTabPinned(int index) const override;
   base::Optional<tab_groups::TabGroupId> GetTabGroupForTab(
       int index) const override;
-  tab_groups::TabGroupVisualData* GetVisualDataForGroup(
-      tab_groups::TabGroupId group) const override;
+  const tab_groups::TabGroupVisualData* GetVisualDataForGroup(
+      const tab_groups::TabGroupId& group) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
   const gfx::Rect GetRestoredBounds() const override;
   ui::WindowShowState GetRestoredState() const override;
   std::string GetWorkspace() const override;
@@ -51,7 +51,7 @@
       int selected_navigation,
       const std::string& extension_app_id,
       base::Optional<tab_groups::TabGroupId> group,
-      const tab_groups::TabGroupVisualData group_visual_data,
+      const tab_groups::TabGroupVisualData& group_visual_data,
       bool select,
       bool pin,
       bool from_last_session,
diff --git a/chrome/browser/ui/android/widget/BUILD.gn b/chrome/browser/ui/android/widget/BUILD.gn
index 95cdb33..211d93c7 100644
--- a/chrome/browser/ui/android/widget/BUILD.gn
+++ b/chrome/browser/ui/android/widget/BUILD.gn
@@ -31,12 +31,6 @@
     "java/src/org/chromium/chrome/browser/ui/widget/animation/CancelAwareAnimatorListener.java",
     "java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java",
     "java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/UiConfig.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/VerticalDisplayStyle.java",
-    "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/ViewResizer.java",
     "java/src/org/chromium/chrome/browser/ui/widget/dragreorder/DragReorderableListAdapter.java",
     "java/src/org/chromium/chrome/browser/ui/widget/dragreorder/DragStateDelegate.java",
     "java/src/org/chromium/chrome/browser/ui/widget/highlight/PulseDrawable.java",
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
index e1c7612..bb22aeb 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
@@ -41,7 +41,9 @@
 void AppServiceAppIconLoader::FetchImage(const std::string& app_id) {
   AppIDToIconMap::const_iterator it = icon_map_.find(app_id);
   if (it != icon_map_.end()) {
-    delegate()->OnAppImageUpdated(app_id, it->second);
+    if (!it->second.isNull()) {
+      delegate()->OnAppImageUpdated(app_id, it->second);
+    }
     return;
   }
 
@@ -57,7 +59,7 @@
 
 void AppServiceAppIconLoader::UpdateImage(const std::string& app_id) {
   AppIDToIconMap::const_iterator it = icon_map_.find(app_id);
-  if (it == icon_map_.end()) {
+  if (it == icon_map_.end() || it->second.isNull()) {
     return;
   }
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index ce1e805..6135210 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -92,10 +92,9 @@
     base::TimeDelta::FromMinutes(1);
 
 // Accessor for deferred set notifications enabled requests in prefs.
-class SetNotificationsEnabledDeferred {
+class NotificationsEnabledDeferred {
  public:
-  explicit SetNotificationsEnabledDeferred(PrefService* prefs)
-      : prefs_(prefs) {}
+  explicit NotificationsEnabledDeferred(PrefService* prefs) : prefs_(prefs) {}
 
   void Put(const std::string& app_id, bool enabled) {
     DictionaryPrefUpdate update(
@@ -104,10 +103,10 @@
     dict->SetKey(app_id, base::Value(enabled));
   }
 
-  bool Get(const std::string& app_id, bool* enabled) {
+  bool Get(const std::string& app_id) {
     const base::DictionaryValue* dict =
         prefs_->GetDictionary(arc::prefs::kArcSetNotificationsEnabledDeferred);
-    return dict->GetBoolean(app_id, enabled);
+    return dict->FindBoolKey(app_id).value_or(false);
   }
 
   void Remove(const std::string& app_id) {
@@ -576,7 +575,7 @@
 
   // In case app is not ready, defer this request.
   if (!ready_apps_.count(app_id)) {
-    SetNotificationsEnabledDeferred(prefs_).Put(app_id, enabled);
+    NotificationsEnabledDeferred(prefs_).Put(app_id, enabled);
     for (auto& observer : observer_list_)
       observer.OnNotificationsEnabledChanged(app_info->package_name, enabled);
     return;
@@ -587,7 +586,7 @@
   if (!app_instance)
     return;
 
-  SetNotificationsEnabledDeferred(prefs_).Remove(app_id);
+  NotificationsEnabledDeferred(prefs_).Remove(app_id);
   app_instance->SetNotificationsEnabled(app_info->package_name, enabled);
 }
 
@@ -626,25 +625,16 @@
       !packages->GetDictionaryWithoutPathExpansion(package_name, &package))
     return std::unique_ptr<PackageInfo>();
 
-  bool uninstalled = false;
-  if (package->GetBoolean(kUninstalled, &uninstalled) && uninstalled)
+  if (package->FindBoolKey(kUninstalled).value_or(false))
     return nullptr;
 
-  int32_t package_version = 0;
   int64_t last_backup_android_id = 0;
   int64_t last_backup_time = 0;
-  bool should_sync = false;
-  bool system = false;
-  bool vpn_provider = false;
   base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr>
       permissions;
 
   GetInt64FromPref(package, kLastBackupAndroidId, &last_backup_android_id);
   GetInt64FromPref(package, kLastBackupTime, &last_backup_time);
-  package->GetInteger(kPackageVersion, &package_version);
-  package->GetBoolean(kShouldSync, &should_sync);
-  package->GetBoolean(kSystem, &system);
-  package->GetBoolean(kVPNProvider, &vpn_provider);
   const base::Value* permission_val = package->FindKey(kPermissionStates);
   if (permission_val) {
     const base::DictionaryValue* permission_dict = nullptr;
@@ -678,8 +668,12 @@
   }
 
   return std::make_unique<PackageInfo>(
-      package_name, package_version, last_backup_android_id, last_backup_time,
-      should_sync, system, vpn_provider, std::move(permissions));
+      package_name, package->FindIntKey(kPackageVersion).value_or(0),
+      last_backup_android_id, last_backup_time,
+      package->FindBoolKey(kShouldSync).value_or(false),
+      package->FindBoolKey(kSystem).value_or(false),
+      package->FindBoolKey(kVPNProvider).value_or(false),
+      std::move(permissions));
 }
 
 std::vector<std::string> ArcAppListPrefs::GetAppIds() const {
@@ -745,22 +739,16 @@
   std::string activity;
   std::string intent_uri;
   std::string icon_resource_id;
-  bool suspended = false;
-  bool sticky = false;
-  bool notifications_enabled = true;
-  bool shortcut = false;
-  bool launchable = true;
+  bool notifications_enabled =
+      app->FindBoolKey(kNotificationsEnabled).value_or(true);
+  const bool shortcut = app->FindBoolKey(kShortcut).value_or(false);
+  const bool launchable = app->FindBoolKey(kLaunchable).value_or(true);
 
   app->GetString(kName, &name);
   app->GetString(kPackageName, &package_name);
   app->GetString(kActivity, &activity);
   app->GetString(kIntentUri, &intent_uri);
   app->GetString(kIconResourceId, &icon_resource_id);
-  app->GetBoolean(kSuspended, &suspended);
-  app->GetBoolean(kSticky, &sticky);
-  app->GetBoolean(kNotificationsEnabled, &notifications_enabled);
-  app->GetBoolean(kShortcut, &shortcut);
-  app->GetBoolean(kLaunchable, &launchable);
 
   DCHECK(!name.empty());
   DCHECK(!shortcut || activity.empty());
@@ -772,14 +760,16 @@
     last_launch_time = base::Time::FromInternalValue(last_launch_time_internal);
   }
 
-  bool deferred;
-  if (SetNotificationsEnabledDeferred(prefs_).Get(app_id, &deferred))
+  const bool deferred = NotificationsEnabledDeferred(prefs_).Get(app_id);
+  if (deferred)
     notifications_enabled = deferred;
 
   return std::make_unique<AppInfo>(
       name, package_name, activity, intent_uri, icon_resource_id,
-      last_launch_time, GetInstallTime(app_id), sticky, notifications_enabled,
-      ready_apps_.count(app_id) > 0 /* ready */, suspended,
+      last_launch_time, GetInstallTime(app_id),
+      app->FindBoolKey(kSticky).value_or(false), notifications_enabled,
+      ready_apps_.count(app_id) > 0 /* ready */,
+      app->FindBoolKey(kSuspended).value_or(false),
       launchable && arc::ShouldShowInLauncher(app_id), shortcut, launchable);
 }
 
@@ -1177,11 +1167,10 @@
   }
 
   if (app_ready) {
-    bool deferred_notifications_enabled;
-    if (SetNotificationsEnabledDeferred(prefs_).Get(
-            app_id, &deferred_notifications_enabled)) {
+    const bool deferred_notifications_enabled =
+        NotificationsEnabledDeferred(prefs_).Get(app_id);
+    if (deferred_notifications_enabled)
       SetNotificationsEnabled(app_id, deferred_notifications_enabled);
-    }
 
     // Invalidate app icons in case it was already registered, becomes ready and
     // icon version is updated. This allows to use previous icons until new
@@ -1277,9 +1266,8 @@
       base::NumberToString(package.last_backup_android_id);
   const std::string time_str = base::NumberToString(package.last_backup_time);
 
-  int old_package_version = -1;
-  package_dict->GetInteger(kPackageVersion, &old_package_version);
-
+  int old_package_version =
+      package_dict->FindIntKey(kPackageVersion).value_or(-1);
   package_dict->SetBoolean(kShouldSync, package.sync);
   package_dict->SetInteger(kPackageVersion, package.package_version);
   package_dict->SetString(kLastBackupAndroidId, id_str);
@@ -1538,17 +1526,15 @@
        app_it.Advance()) {
     const base::Value* value = &app_it.value();
     const base::DictionaryValue* app;
-    bool shortcut;
     std::string installed_package_name;
     std::string installed_intent_uri;
     if (!value->GetAsDictionary(&app) ||
-        !app->GetBoolean(kShortcut, &shortcut) ||
         !app->GetString(kPackageName, &installed_package_name) ||
         !app->GetString(kIntentUri, &installed_intent_uri)) {
       VLOG(2) << "Failed to extract information for " << app_it.key() << ".";
       continue;
     }
-
+    const bool shortcut = app->FindBoolKey(kShortcut).value_or(false);
     if (!shortcut || installed_package_name != package_name ||
         installed_intent_uri != intent_uri) {
       continue;
@@ -1597,15 +1583,13 @@
       continue;
 
     if (!include_shortcuts) {
-      bool shortcut = false;
-      if (app->GetBoolean(kShortcut, &shortcut) && shortcut)
+      if (app->FindBoolKey(kShortcut).value_or(false))
         continue;
     }
 
     if (include_only_launchable_apps) {
       // Filter out non-lauchable apps.
-      bool launchable = false;
-      if (!app->GetBoolean(kLaunchable, &launchable) || !launchable)
+      if (!app->FindBoolKey(kLaunchable).value_or(false))
         continue;
     }
 
@@ -1816,8 +1800,8 @@
       continue;
     }
 
-    bool uninstalled = false;
-    package_info->GetBoolean(kUninstalled, &uninstalled);
+    const bool uninstalled =
+        package_info->FindBoolKey(kUninstalled).value_or(false);
     if (installed != !uninstalled)
       continue;
 
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index da6d01c..f5c500b 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -375,10 +375,9 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppDeferredLauncherWithParamsBrowserTest);
 };
 
-// TODO(crbug.com/1038602): Fix this flaky test, and enable it again.
 // This tests simulates normal workflow for starting ARC app in deferred mode.
 IN_PROC_BROWSER_TEST_P(ArcAppDeferredLauncherWithParamsBrowserTest,
-                       DISABLED_StartAppDeferred) {
+                       StartAppDeferred) {
   // Install app to remember existing apps.
   StartInstance();
   InstallTestApps(kTestAppPackage, false);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index b97c671..d31391e2 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1127,7 +1127,7 @@
     SessionService* const session_service =
         SessionServiceFactory::GetForProfile(profile_);
     if (session_service) {
-      tab_groups::TabGroupVisualData* visual_data =
+      const tab_groups::TabGroupVisualData* visual_data =
           tab_strip_model_->group_model()
               ->GetTabGroup(change.group)
               ->visual_data();
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc
index 4a379bf3..633b1f2f 100644
--- a/chrome/browser/ui/browser_live_tab_context.cc
+++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -98,8 +98,9 @@
   return browser_->tab_strip_model()->GetTabGroupForTab(index);
 }
 
-tab_groups::TabGroupVisualData* BrowserLiveTabContext::GetVisualDataForGroup(
-    tab_groups::TabGroupId group) const {
+const tab_groups::TabGroupVisualData*
+BrowserLiveTabContext::GetVisualDataForGroup(
+    const tab_groups::TabGroupId& group) const {
   return browser_->tab_strip_model()
       ->group_model()
       ->GetTabGroup(group)
@@ -107,8 +108,8 @@
 }
 
 void BrowserLiveTabContext::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& visual_data) {
   browser_->tab_strip_model()->group_model()->GetTabGroup(group)->SetVisualData(
       std::move(visual_data));
 }
@@ -131,7 +132,7 @@
     int selected_navigation,
     const std::string& extension_app_id,
     base::Optional<tab_groups::TabGroupId> group,
-    const tab_groups::TabGroupVisualData group_visual_data,
+    const tab_groups::TabGroupVisualData& group_visual_data,
     bool select,
     bool pin,
     bool from_last_session,
diff --git a/chrome/browser/ui/browser_live_tab_context.h b/chrome/browser/ui/browser_live_tab_context.h
index 3a64e862..68322c8 100644
--- a/chrome/browser/ui/browser_live_tab_context.h
+++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -44,11 +44,11 @@
   bool IsTabPinned(int index) const override;
   base::Optional<tab_groups::TabGroupId> GetTabGroupForTab(
       int index) const override;
-  tab_groups::TabGroupVisualData* GetVisualDataForGroup(
-      tab_groups::TabGroupId group) const override;
+  const tab_groups::TabGroupVisualData* GetVisualDataForGroup(
+      const tab_groups::TabGroupId& group) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
   const gfx::Rect GetRestoredBounds() const override;
   ui::WindowShowState GetRestoredState() const override;
   std::string GetWorkspace() const override;
@@ -59,7 +59,7 @@
       int selected_navigation,
       const std::string& extension_app_id,
       base::Optional<tab_groups::TabGroupId> group,
-      const tab_groups::TabGroupVisualData group_visual_data,
+      const tab_groups::TabGroupVisualData& group_visual_data,
       bool select,
       bool pin,
       bool from_last_session,
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
index f08a848..38c1364 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -482,7 +482,9 @@
 
   // Windows created with NSBorderlessWindowMask by default don't have shadow,
   // but packaged apps should always have one.
-  EXPECT_TRUE([ns_window hasShadow]);
+  // This specific check is disabled because shadows are disabled on the
+  // bots - see https://crbug.com/899286.
+  // EXPECT_TRUE([ns_window hasShadow]);
 
   // Since the window has no constraints, it should have all of the following
   // style mask bits.
diff --git a/chrome/browser/ui/cocoa/notifications/BUILD.gn b/chrome/browser/ui/cocoa/notifications/BUILD.gn
index 0f07a25..8e06dc2 100644
--- a/chrome/browser/ui/cocoa/notifications/BUILD.gn
+++ b/chrome/browser/ui/cocoa/notifications/BUILD.gn
@@ -36,12 +36,12 @@
   ldflags = []
   if (is_component_build) {
     ldflags += [
-      # The XPC service is in Chromium.app/Contents/Versions/X/Chromium \
+      # The XPC service is in Chromium.app/Contents/Frameworks/Chromium \
       # Framework.framework/Versions/A/XPCServices/ \
       # AlertNotificationService.xpc/Contents/MacOS/
       # so set rpath up to the base.
       "-rpath",
-      "@loader_path/../../../../../../../../../../../",
+      "@loader_path/../../../../../../../../../../",
     ]
   }
 }
diff --git a/chrome/browser/ui/color/OWNERS b/chrome/browser/ui/color/OWNERS
new file mode 100644
index 0000000..5b9ae4a
--- /dev/null
+++ b/chrome/browser/ui/color/OWNERS
@@ -0,0 +1 @@
+file://ui/color/OWNERS
\ No newline at end of file
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index e553b6c..db5e815 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -83,6 +83,7 @@
 #include "net/base/host_port_pair.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/request_handler_util.h"
 #include "testing/gtest/include/gtest/gtest-param-test.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -1727,6 +1728,21 @@
   void SetUpOnMainThread() override {
     HostedAppTest::SetUpOnMainThread();
     host_resolver()->AddRule("*", "127.0.0.1");
+
+    // Some tests make requests to URLs that purposefully end with a double
+    // slash to test this edge case (note that "//" is a valid path).  Install
+    // a custom handler to return dummy content for such requests before
+    // starting the test server.
+    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+        [](const net::test_server::HttpRequest& request)
+            -> std::unique_ptr<net::test_server::HttpResponse> {
+          if (request.relative_url == "//") {
+            return std::make_unique<net::test_server::RawHttpResponse>(
+                "HTTP/1.1 200 OK", "Hello there!");
+          }
+          return nullptr;
+        }));
+
     embedded_test_server()->StartAcceptingConnections();
 
     should_swap_for_cross_site_ = content::AreAllSitesIsolatedForTesting();
@@ -2200,6 +2216,49 @@
   EXPECT_FALSE(registrar().IsInstalled(app_->id()));
 }
 
+// Check that we can successfully complete a navigation to an app URL with a
+// "//" path (on which GURL::Resolve() currently fails due to
+// https://crbug.com/1034197), and that the resulting SiteInstance has a valid
+// site URL. See https://crbug.com/1016954.
+IN_PROC_BROWSER_TEST_P(HostedAppProcessModelTest,
+                       NavigateToAppURLWithDoubleSlashPath) {
+  // Set up and launch the hosted app.
+  GURL app_url =
+      embedded_test_server()->GetURL("app.site.com", "/frame_tree/simple.htm");
+  extensions::TestExtensionDir test_app_dir;
+  test_app_dir.WriteManifest(base::StringPrintf(kHostedAppProcessModelManifest,
+                                                app_url.spec().c_str()));
+  SetupApp(test_app_dir.UnpackedPath());
+
+  // Navigate to a URL under the app's extent, but with a path (//) that
+  // GURL::Resolve() fails to resolve against a relative URL (see the
+  // explanation in https://crbug.com/1034197).  Avoid giving the "//" directly
+  // to EmbeddedTestServer::GetURL(), which also uses GURL::Resolve()
+  // internally and would otherwise produce an empty/invalid URL to navigate
+  // to.
+  GURL double_slash_path_app_url =
+      embedded_test_server()->GetURL("isolated.site.com", "/");
+  GURL::Replacements replace_path;
+  replace_path.SetPathStr("//");
+  double_slash_path_app_url =
+      double_slash_path_app_url.ReplaceComponents(replace_path);
+
+  ui_test_utils::NavigateToURL(browser(), double_slash_path_app_url);
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  RenderFrameHost* main_frame = contents->GetMainFrame();
+  EXPECT_EQ(double_slash_path_app_url, main_frame->GetLastCommittedURL());
+
+  // The resulting page should load in an app process, and the corresponding
+  // SiteInstance's site URL should be a valid, non-empty chrome-extension://
+  // URL with a valid host that corresponds to the app's ID.
+  EXPECT_TRUE(process_map_->Contains(main_frame->GetProcess()->GetID()));
+  EXPECT_FALSE(main_frame->GetSiteInstance()->GetSiteURL().is_empty());
+  EXPECT_TRUE(main_frame->GetSiteInstance()->GetSiteURL().SchemeIs(
+      extensions::kExtensionScheme));
+  EXPECT_EQ(main_frame->GetSiteInstance()->GetSiteURL().host(), app_->id());
+}
+
 // Helper class that sets up two isolated origins, where one is a subdomain of
 // the other: https://isolated.com and https://very.isolated.com.
 class HostedAppIsolatedOriginTest : public HostedAppProcessModelTest {
diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn
index 130474cd..765c6c9d 100644
--- a/chrome/browser/ui/messages/android/BUILD.gn
+++ b/chrome/browser/ui/messages/android/BUILD.gn
@@ -14,11 +14,11 @@
 }
 
 android_library("java") {
-  java_files = [
-    "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java",
+  sources = [
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollection.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarManager.java",
+    "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java",
   ]
   deps = [
     ":java_resources",
@@ -62,6 +62,6 @@
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
-    "//ui/android:ui_java_test_support"
+    "//ui/android:ui_java_test_support",
   ]
 }
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 8248c08..e2233fc 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -791,11 +791,10 @@
                                          bool shift_key) {
   if (!search::DefaultSearchProviderIsGoogle(profile()))
     return;
-  bool middle_button = (button == 1.0);
-  WindowOpenDisposition disposition = ui::DispositionFromClick(
-      middle_button, alt_key, ctrl_key, meta_key, shift_key);
-  if (button > 1)
-    disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+  WindowOpenDisposition disposition =
+      (button > 1) ? WindowOpenDisposition::NEW_FOREGROUND_TAB
+                   : ui::DispositionFromClick((button == 1.0), alt_key,
+                                              ctrl_key, meta_key, shift_key);
   web_contents_->OpenURL(content::OpenURLParams(
       GURL(chrome::kChromeUIExtensionsURL), content::Referrer(), disposition,
       ui::PAGE_TRANSITION_LINK, false));
diff --git a/chrome/browser/ui/tabs/tab_group.cc b/chrome/browser/ui/tabs/tab_group.cc
index ce8151d..645c3746 100644
--- a/chrome/browser/ui/tabs/tab_group.cc
+++ b/chrome/browser/ui/tabs/tab_group.cc
@@ -20,15 +20,16 @@
 #include "ui/gfx/text_elider.h"
 
 TabGroup::TabGroup(TabGroupController* controller,
-                   tab_groups::TabGroupId id,
-                   tab_groups::TabGroupVisualData visual_data)
+                   const tab_groups::TabGroupId& id,
+                   const tab_groups::TabGroupVisualData& visual_data)
     : controller_(controller), id_(id) {
   visual_data_ = std::make_unique<tab_groups::TabGroupVisualData>(visual_data);
 }
 
 TabGroup::~TabGroup() {}
 
-void TabGroup::SetVisualData(tab_groups::TabGroupVisualData visual_data) {
+void TabGroup::SetVisualData(
+    const tab_groups::TabGroupVisualData& visual_data) {
   visual_data_ = std::make_unique<tab_groups::TabGroupVisualData>(visual_data);
   controller_->ChangeTabGroupVisuals(id_);
 }
diff --git a/chrome/browser/ui/tabs/tab_group.h b/chrome/browser/ui/tabs/tab_group.h
index 8931c38..62c7927b 100644
--- a/chrome/browser/ui/tabs/tab_group.h
+++ b/chrome/browser/ui/tabs/tab_group.h
@@ -26,15 +26,15 @@
 class TabGroup {
  public:
   TabGroup(TabGroupController* controller,
-           tab_groups::TabGroupId id,
-           tab_groups::TabGroupVisualData visual_data);
+           const tab_groups::TabGroupId& id,
+           const tab_groups::TabGroupVisualData& visual_data);
   ~TabGroup();
 
-  tab_groups::TabGroupId id() const { return id_; }
-  tab_groups::TabGroupVisualData* visual_data() const {
+  const tab_groups::TabGroupId& id() const { return id_; }
+  const tab_groups::TabGroupVisualData* visual_data() const {
     return visual_data_.get();
   }
-  void SetVisualData(tab_groups::TabGroupVisualData visual_data);
+  void SetVisualData(const tab_groups::TabGroupVisualData& visual_data);
 
   // Returns the user-visible group title that will be displayed in context
   // menus and tooltips. Generates a descriptive placeholder if the user has
diff --git a/chrome/browser/ui/tabs/tab_group_controller.h b/chrome/browser/ui/tabs/tab_group_controller.h
index 6d22c935..3be4334 100644
--- a/chrome/browser/ui/tabs/tab_group_controller.h
+++ b/chrome/browser/ui/tabs/tab_group_controller.h
@@ -17,10 +17,10 @@
 
 class TabGroupController {
  public:
-  virtual void CreateTabGroup(tab_groups::TabGroupId group) = 0;
-  virtual void ChangeTabGroupContents(tab_groups::TabGroupId group) = 0;
-  virtual void ChangeTabGroupVisuals(tab_groups::TabGroupId group) = 0;
-  virtual void CloseTabGroup(tab_groups::TabGroupId group) = 0;
+  virtual void CreateTabGroup(const tab_groups::TabGroupId& group) = 0;
+  virtual void ChangeTabGroupContents(const tab_groups::TabGroupId& group) = 0;
+  virtual void ChangeTabGroupVisuals(const tab_groups::TabGroupId& group) = 0;
+  virtual void CloseTabGroup(const tab_groups::TabGroupId& group) = 0;
 
   // Methods from TabStipModel that are exposed to TabGroup.
   virtual base::Optional<tab_groups::TabGroupId> GetTabGroupForTab(
diff --git a/chrome/browser/ui/tabs/tab_group_model.cc b/chrome/browser/ui/tabs/tab_group_model.cc
index 9754728..3aeb6eab 100644
--- a/chrome/browser/ui/tabs/tab_group_model.cc
+++ b/chrome/browser/ui/tabs/tab_group_model.cc
@@ -22,7 +22,7 @@
 TabGroupModel::~TabGroupModel() {}
 
 TabGroup* TabGroupModel::AddTabGroup(
-    tab_groups::TabGroupId id,
+    const tab_groups::TabGroupId& id,
     base::Optional<tab_groups::TabGroupVisualData> visual_data) {
   auto tab_group = std::make_unique<TabGroup>(
       controller_, id,
@@ -33,16 +33,16 @@
   return groups_[id].get();
 }
 
-bool TabGroupModel::ContainsTabGroup(tab_groups::TabGroupId id) const {
+bool TabGroupModel::ContainsTabGroup(const tab_groups::TabGroupId& id) const {
   return base::Contains(groups_, id);
 }
 
-TabGroup* TabGroupModel::GetTabGroup(tab_groups::TabGroupId id) const {
+TabGroup* TabGroupModel::GetTabGroup(const tab_groups::TabGroupId& id) const {
   DCHECK(ContainsTabGroup(id));
   return groups_.find(id)->second.get();
 }
 
-void TabGroupModel::RemoveTabGroup(tab_groups::TabGroupId id) {
+void TabGroupModel::RemoveTabGroup(const tab_groups::TabGroupId& id) {
   DCHECK(ContainsTabGroup(id));
   groups_.erase(id);
 }
diff --git a/chrome/browser/ui/tabs/tab_group_model.h b/chrome/browser/ui/tabs/tab_group_model.h
index c0528a7..24facab 100644
--- a/chrome/browser/ui/tabs/tab_group_model.h
+++ b/chrome/browser/ui/tabs/tab_group_model.h
@@ -13,12 +13,12 @@
 #include <vector>
 
 #include "base/optional.h"
-#include "components/tab_groups/tab_group_color.h"
 
 class TabGroup;
 class TabGroupController;
 
 namespace tab_groups {
+enum class TabGroupColorId;
 class TabGroupId;
 class TabGroupVisualData;
 }  // namespace tab_groups
@@ -38,18 +38,18 @@
   // initially be empty, but the expectation is that at least one tab will be
   // added to it immediately.
   TabGroup* AddTabGroup(
-      tab_groups::TabGroupId id,
+      const tab_groups::TabGroupId& id,
       base::Optional<tab_groups::TabGroupVisualData> visual_data);
 
   // Returns whether a tab group with the given |id| exists.
-  bool ContainsTabGroup(tab_groups::TabGroupId id) const;
+  bool ContainsTabGroup(const tab_groups::TabGroupId& id) const;
 
   // Returns the tab group with the given |id|. The group must exist.
-  TabGroup* GetTabGroup(tab_groups::TabGroupId id) const;
+  TabGroup* GetTabGroup(const tab_groups::TabGroupId& id) const;
 
   // Removes the tab group with the given |id| from the registry. Should be
   // called whenever the group becomes empty.
-  void RemoveTabGroup(tab_groups::TabGroupId id);
+  void RemoveTabGroup(const tab_groups::TabGroupId& id);
 
   std::vector<tab_groups::TabGroupId> ListTabGroups() const;
 
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index 95f2134d..dc671c9 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1893,25 +1893,26 @@
   group_model_->GetTabGroup(group)->AddTab();
 }
 
-void TabStripModel::CreateTabGroup(tab_groups::TabGroupId group) {
+void TabStripModel::CreateTabGroup(const tab_groups::TabGroupId& group) {
   TabGroupChange change(group, TabGroupChange::kCreated);
   for (auto& observer : observers_)
     observer.OnTabGroupChanged(change);
 }
 
-void TabStripModel::ChangeTabGroupContents(tab_groups::TabGroupId group) {
+void TabStripModel::ChangeTabGroupContents(
+    const tab_groups::TabGroupId& group) {
   TabGroupChange change(group, TabGroupChange::kContentsChanged);
   for (auto& observer : observers_)
     observer.OnTabGroupChanged(change);
 }
 
-void TabStripModel::ChangeTabGroupVisuals(tab_groups::TabGroupId group) {
+void TabStripModel::ChangeTabGroupVisuals(const tab_groups::TabGroupId& group) {
   TabGroupChange change(group, TabGroupChange::kVisualsChanged);
   for (auto& observer : observers_)
     observer.OnTabGroupChanged(change);
 }
 
-void TabStripModel::CloseTabGroup(tab_groups::TabGroupId group) {
+void TabStripModel::CloseTabGroup(const tab_groups::TabGroupId& group) {
   TabGroupChange change(group, TabGroupChange::kClosed);
   for (auto& observer : observers_)
     observer.OnTabGroupChanged(change);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h
index bc785ac..cac5de7 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.h
+++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -678,10 +678,10 @@
   void GroupTab(int index, tab_groups::TabGroupId group);
 
   // TabGroupController:
-  void CreateTabGroup(tab_groups::TabGroupId group) override;
-  void ChangeTabGroupContents(tab_groups::TabGroupId group) override;
-  void ChangeTabGroupVisuals(tab_groups::TabGroupId group) override;
-  void CloseTabGroup(tab_groups::TabGroupId group) override;
+  void CreateTabGroup(const tab_groups::TabGroupId& group) override;
+  void ChangeTabGroupContents(const tab_groups::TabGroupId& group) override;
+  void ChangeTabGroupVisuals(const tab_groups::TabGroupId& group) override;
+  void CloseTabGroup(const tab_groups::TabGroupId& group) override;
   // The same as count(), but overridden for TabGroup to access.
   int GetTabCount() const override;
 
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index c7a513b..9868bf7 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -259,12 +259,8 @@
   DCHECK_NE(IDC_RECENT_TABS_NO_DEVICE_TABS, command_id);
   DCHECK(!IsDeviceNameCommandId(command_id));
 
-  WindowOpenDisposition disposition =
-      ui::DispositionFromEventFlags(event_flags);
-  if (disposition == WindowOpenDisposition::CURRENT_TAB) {
-    // Force to open a new foreground tab.
-    disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-  }
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
 
   sessions::TabRestoreService* service =
       TabRestoreServiceFactory::GetForProfile(browser_->profile());
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
index 8b7ef76..e1f2cf3 100644
--- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
+++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -80,8 +80,8 @@
   void OpenLink(const std::string& url, int event_flags);
 
   Browser* browser_;
-  views::Link* high_contrast_;
-  views::Link* dark_theme_;
+  views::Link* high_contrast_ = nullptr;
+  views::Link* dark_theme_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(InvertBubbleView);
 };
@@ -89,9 +89,7 @@
 InvertBubbleView::InvertBubbleView(Browser* browser, views::View* anchor_view)
     : views::BubbleDialogDelegateView(anchor_view,
                                       views::BubbleBorder::TOP_RIGHT),
-      browser_(browser),
-      high_contrast_(nullptr),
-      dark_theme_(nullptr) {
+      browser_(browser) {
   DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK);
   DialogDelegate::set_button_label(ui::DIALOG_BUTTON_OK,
                                    l10n_util::GetStringUTF16(IDS_DONE));
@@ -108,15 +106,6 @@
   SetBorder(views::CreateEmptyBorder(
       provider->GetInsetsMetric(views::INSETS_DIALOG)));
 
-  auto high_contrast = std::make_unique<views::Link>(
-      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT),
-      CONTEXT_BODY_TEXT_LARGE);
-  high_contrast->set_listener(this);
-
-  auto dark_theme = std::make_unique<views::Link>(
-      l10n_util::GetStringUTF16(IDS_DARK_THEME), CONTEXT_BODY_TEXT_LARGE);
-  dark_theme->set_listener(this);
-
   views::BoxLayout* layout =
       SetLayoutManager(std::make_unique<views::BoxLayout>(
           views::BoxLayout::Orientation::kVertical));
@@ -126,8 +115,15 @@
   AddChildView(std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_HEADER),
       CONTEXT_BODY_TEXT_LARGE));
-  high_contrast_ = AddChildView(std::move(high_contrast));
-  dark_theme_ = AddChildView(std::move(dark_theme));
+
+  high_contrast_ = AddChildView(std::make_unique<views::Link>(
+      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT),
+      CONTEXT_BODY_TEXT_LARGE));
+  high_contrast_->set_listener(this);
+
+  dark_theme_ = AddChildView(std::make_unique<views::Link>(
+      l10n_util::GetStringUTF16(IDS_DARK_THEME), CONTEXT_BODY_TEXT_LARGE));
+  dark_theme_->set_listener(this);
 
   // Switching to high-contrast mode has a nasty habit of causing Chrome
   // top-level windows to lose focus, so closing the bubble on deactivate
@@ -161,14 +157,10 @@
 }
 
 void InvertBubbleView::OpenLink(const std::string& url, int event_flags) {
-  WindowOpenDisposition disposition =
-      ui::DispositionFromEventFlags(event_flags);
-  content::OpenURLParams params(
-      GURL(url), content::Referrer(),
-      disposition == WindowOpenDisposition::CURRENT_TAB
-          ? WindowOpenDisposition::NEW_FOREGROUND_TAB
-          : disposition,
-      ui::PAGE_TRANSITION_LINK, false);
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+  content::OpenURLParams params(GURL(url), content::Referrer(), disposition,
+                                ui::PAGE_TRANSITION_LINK, false);
   browser_->OpenURL(params);
 }
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
index febd19e..02b1fd28 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -59,12 +59,10 @@
  public:
   explicit AppInfoDialogTestApi(AppInfoDialog* dialog) : dialog_(dialog) {}
 
-  AppInfoHeaderPanel* header_panel() {
-    return static_cast<AppInfoHeaderPanel*>(dialog_->children().front());
-  }
-
-  views::Link* view_in_store_link() {
-    return header_panel()->view_in_store_link_;
+  void ShowAppInWebStore() {
+    auto* header_panel =
+        static_cast<AppInfoHeaderPanel*>(dialog_->children().front());
+    return header_panel->ShowAppInWebStore();
   }
 
  private:
@@ -264,16 +262,14 @@
 // dialog cleanly.
 TEST_F(AppInfoDialogViewsTest, ViewInStore) {
   ShowAppInfo(kTestExtensionId);
-  EXPECT_TRUE(extension_->from_webstore());  // Otherwise there is no link.
-  views::Link* link = test::AppInfoDialogTestApi(dialog_).view_in_store_link();
-  EXPECT_TRUE(link);
+  ASSERT_TRUE(extension_->from_webstore());
 
   TabStripModel* tabs = browser()->tab_strip_model();
   EXPECT_EQ(0, tabs->count());
 
   ASSERT_TRUE(widget_);
   EXPECT_FALSE(widget_->IsClosed());
-  link->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0));
+  test::AppInfoDialogTestApi(dialog_).ShowAppInWebStore();
 
   ASSERT_TRUE(widget_);
   EXPECT_TRUE(widget_->IsClosed());
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
index 7da1657..cd0f6d7 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
@@ -63,6 +63,10 @@
 AppInfoHeaderPanel::~AppInfoHeaderPanel() {
 }
 
+void AppInfoHeaderPanel::OnIconUpdated(extensions::ChromeAppIcon* icon) {
+  app_icon_view_->SetImage(icon->image_skia());
+}
+
 void AppInfoHeaderPanel::CreateControls() {
   auto app_icon_view = std::make_unique<views::ImageView>();
   app_icon_view->SetImageSize(gfx::Size(kAppIconSize, kAppIconSize));
@@ -88,13 +92,12 @@
       vertical_info_container_ptr->AddChildView(std::move(app_name_label));
 
   if (CanShowAppInWebStore()) {
-    auto view_in_store_link = std::make_unique<views::Link>(
-        l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK));
+    auto* view_in_store_link =
+        vertical_info_container_ptr->AddChildView(std::make_unique<views::Link>(
+            l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK)));
     view_in_store_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     view_in_store_link->set_listener(this);
     view_in_store_link->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
-    view_in_store_link_ = vertical_info_container_ptr->AddChildView(
-        std::move(view_in_store_link));
   } else {
     // If there's no link, allow the app's name to take up multiple lines.
     // TODO(sashab): Limit the number of lines to 2.
@@ -103,14 +106,9 @@
 }
 
 void AppInfoHeaderPanel::LinkClicked(views::Link* source, int event_flags) {
-  DCHECK_EQ(source, view_in_store_link_);
   ShowAppInWebStore();
 }
 
-void AppInfoHeaderPanel::OnIconUpdated(extensions::ChromeAppIcon* icon) {
-  app_icon_view_->SetImage(icon->image_skia());
-}
-
 void AppInfoHeaderPanel::ShowAppInWebStore() {
   DCHECK(CanShowAppInWebStore());
   Close();
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.h
index 9a4ecc3..6170d39 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.h
@@ -39,14 +39,14 @@
  private:
   friend class test::AppInfoDialogTestApi;
 
-  void CreateControls();
-
   // Overridden from views::LinkListener:
   void LinkClicked(views::Link* source, int event_flags) override;
 
   // extensions::ChromeAppIconDelegate:
   void OnIconUpdated(extensions::ChromeAppIcon* icon) override;
 
+  void CreateControls();
+
   // Opens the app in the web store. Must only be called if
   // CanShowAppInWebStore() returns true.
   void ShowAppInWebStore();
@@ -54,7 +54,6 @@
 
   // UI elements on the dialog. Elements are nullptr if they are not displayed.
   views::ImageView* app_icon_view_ = nullptr;
-  views::Link* view_in_store_link_ = nullptr;
 
   std::unique_ptr<extensions::ChromeAppIcon> app_icon_;
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
index 8eeb708..15856ac 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -98,11 +98,7 @@
 
 AppInfoSummaryPanel::AppInfoSummaryPanel(Profile* profile,
                                          const extensions::Extension* app)
-    : AppInfoPanel(profile, app),
-      size_value_(nullptr),
-      homepage_link_(nullptr),
-      licenses_link_(nullptr),
-      launch_options_combobox_(nullptr) {
+    : AppInfoPanel(profile, app) {
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical, gfx::Insets(),
       ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -126,10 +122,10 @@
               DISTANCE_RELATED_CONTROL_VERTICAL_SMALL)));
 
   if (!app_->description().empty()) {
-    const size_t max_length = 400;
+    constexpr size_t kMaxLength = 400;
     base::string16 text = base::UTF8ToUTF16(app_->description());
-    if (text.length() > max_length) {
-      text = text.substr(0, max_length);
+    if (text.length() > kMaxLength) {
+      text = text.substr(0, kMaxLength - 5);
       text += base::ASCIIToUTF16(" ... ");
     }
 
@@ -138,25 +134,18 @@
     description_and_labels_stack->AddChildView(std::move(description_label));
   }
 
-  if (CanShowAppHomePage()) {
-    auto homepage_link = std::make_unique<views::Link>(
-        l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_HOMEPAGE_LINK));
-    homepage_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    homepage_link->set_listener(this);
-    homepage_link->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
-    homepage_link_ =
-        description_and_labels_stack->AddChildView(std::move(homepage_link));
-  }
-
-  if (CanDisplayLicenses()) {
-    auto licenses_link = std::make_unique<views::Link>(
-        l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LICENSES_BUTTON_TEXT));
-    licenses_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    licenses_link->set_listener(this);
-    licenses_link->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
-    licenses_link_ =
-        description_and_labels_stack->AddChildView(std::move(licenses_link));
-  }
+  const auto add_link = [&](int message_id) {
+    auto* link = description_and_labels_stack->AddChildView(
+        std::make_unique<views::Link>(l10n_util::GetStringUTF16(message_id)));
+    link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    link->set_listener(this);
+    link->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
+    return link;
+  };
+  if (CanShowAppHomePage())
+    homepage_link_ = add_link(IDS_APPLICATION_INFO_HOMEPAGE_LINK);
+  if (CanDisplayLicenses())
+    licenses_link_ = add_link(IDS_APPLICATION_INFO_LICENSES_BUTTON_TEXT);
 
   vertical_stack->AddChildView(std::move(description_and_labels_stack));
 }
@@ -281,6 +270,7 @@
   return !app_->is_platform_app() && !app_->is_extension() &&
          app_->id() != extension_misc::kChromeAppId;
 }
+
 void AppInfoSummaryPanel::ShowAppHomePage() {
   DCHECK(CanShowAppHomePage());
   OpenLink(extensions::ManifestURL::GetHomepageURL(app_));
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h
index 0132f8ff..fe4551ba 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h
@@ -26,7 +26,6 @@
 namespace views {
 class Combobox;
 class Label;
-class Link;
 class View;
 }
 
@@ -79,12 +78,12 @@
   const std::vector<GURL> GetLicenseUrls() const;
 
   // UI elements on the dialog.
-  views::Label* size_value_;
-  views::Link* homepage_link_;
-  views::Link* licenses_link_;
+  views::Label* size_value_ = nullptr;
+  views::View* homepage_link_ = nullptr;
+  views::View* licenses_link_ = nullptr;
 
   std::unique_ptr<LaunchOptionsComboboxModel> launch_options_combobox_model_;
-  views::Combobox* launch_options_combobox_;
+  views::Combobox* launch_options_combobox_ = nullptr;
 
   base::WeakPtrFactory<AppInfoSummaryPanel> weak_ptr_factory_{this};
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
index e5e04cb..96c8803 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
@@ -23,9 +23,7 @@
 
 ArcAppInfoLinksPanel::ArcAppInfoLinksPanel(Profile* profile,
                                            const extensions::Extension* app)
-    : AppInfoPanel(profile, app),
-      app_list_observer_(this),
-      manage_link_(nullptr) {
+    : AppInfoPanel(profile, app) {
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical, gfx::Insets(),
       ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -50,11 +48,9 @@
 ArcAppInfoLinksPanel::~ArcAppInfoLinksPanel() {}
 
 void ArcAppInfoLinksPanel::LinkClicked(views::Link* source, int event_flags) {
-  DCHECK_EQ(manage_link_, source);
+  gfx::NativeView native_view = GetWidget()->GetNativeView();
   const int64_t display_id =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestView(source->GetWidget()->GetNativeView())
-          .id();
+      display::Screen::GetScreen()->GetDisplayNearestView(native_view).id();
   if (arc::ShowPackageInfo(
           arc::ArcIntentHelperBridge::kArcIntentHelperPackageName,
           arc::mojom::ShowPackageInfoPage::MANAGE_LINKS, display_id)) {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.h
index b13e2723..704899bf6 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.h
@@ -46,8 +46,9 @@
 
   void UpdateLink(bool enabled);
 
-  ScopedObserver<ArcAppListPrefs, ArcAppListPrefs::Observer> app_list_observer_;
-  views::Link* manage_link_;
+  ScopedObserver<ArcAppListPrefs, ArcAppListPrefs::Observer> app_list_observer_{
+      this};
+  views::Link* manage_link_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(ArcAppInfoLinksPanel);
 };
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
index c08af49..33e33b3 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
@@ -184,7 +184,6 @@
 }
 
 void CardUnmaskPromptViews::LinkClicked(views::Link* source, int event_flags) {
-  DCHECK_EQ(source, new_card_link_);
   controller_->NewCardLinkClicked();
   for (views::View* child : input_row_->children())
     child->SetVisible(true);
@@ -230,11 +229,11 @@
   if (new_card_link_)
     return;
 
-  new_card_link_ = new views::Link(
+  auto new_card_link = std::make_unique<views::Link>(
       l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_UNMASK_NEW_CARD_LINK));
-  new_card_link_->SetUnderline(false);
-  new_card_link_->set_listener(this);
-  input_row_->AddChildView(new_card_link_);
+  new_card_link->SetUnderline(false);
+  new_card_link->set_listener(this);
+  new_card_link_ = input_row_->AddChildView(std::move(new_card_link));
 }
 
 views::View* CardUnmaskPromptViews::GetContentsView() {
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h
index d3582fa..cbe09db 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h
@@ -23,7 +23,6 @@
 namespace views {
 class Checkbox;
 class Label;
-class Link;
 class Textfield;
 class Throbber;
 }  // namespace views
@@ -103,7 +102,7 @@
   MonthComboboxModel month_combobox_model_;
   YearComboboxModel year_combobox_model_;
 
-  views::Link* new_card_link_ = nullptr;
+  views::View* new_card_link_ = nullptr;
 
   // The error row view and label for most errors, which live beneath the
   // inputs.
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 626da9e..eb673a3a 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -50,66 +50,6 @@
 
 namespace {
 
-// Display a maximum of 4 visible items in a list before scrolling.
-const int kMaxVisibleListItems = 4;
-
-// Padding for list items and icons.
-const gfx::Insets kTitleDescriptionListItemInset = gfx::Insets(3, 0, 13, 0);
-
-// Returns a view with the given title and description.
-std::unique_ptr<views::View> ConstructTitleDescriptionItemContents(
-    const base::string16& title,
-    const base::string16& description) {
-  auto label_container = std::make_unique<views::View>();
-  label_container->SetBorder(
-      views::CreateEmptyBorder(kTitleDescriptionListItemInset));
-  label_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
-      views::BoxLayout::Orientation::kVertical, gfx::Insets(), 0));
-  if (!title.empty()) {
-    auto title_label = std::make_unique<views::Label>(
-        title, views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY,
-        gfx::DirectionalityMode::DIRECTIONALITY_FROM_UI);
-    title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    title_label->SetAllowCharacterBreak(true);
-    label_container->AddChildView(title_label.release());
-  }
-  if (!description.empty()) {
-    auto description_label = std::make_unique<views::Label>(
-        description, views::style::CONTEXT_LABEL, views::style::STYLE_DISABLED,
-        gfx::DirectionalityMode::DIRECTIONALITY_FROM_UI);
-    description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    description_label->SetAllowCharacterBreak(true);
-    label_container->AddChildView(description_label.release());
-  }
-  return label_container;
-}
-
-// Constructs a view for a list item containing a link.
-std::unique_ptr<views::Link> ConstructLinkItemContents(
-    const base::string16& title,
-    views::LinkListener* parent_) {
-  auto link = std::make_unique<views::Link>(title);
-  link->SetElideBehavior(gfx::ELIDE_MIDDLE);
-  link->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
-  link->set_listener(parent_);
-  return link;
-}
-
-// Constructs an ImageView for a list item with the given icon.
-std::unique_ptr<views::ImageView> ConstructItemIcon(
-    const gfx::VectorIcon* icon,
-    const gfx::VectorIcon& badge) {
-  auto icon_view = std::make_unique<views::ImageView>();
-  DCHECK(icon);
-  icon_view->SetBorder(
-      views::CreateEmptyBorder(kTitleDescriptionListItemInset));
-  const SkColor icon_color = views::style::GetColor(
-      *icon_view, CONTEXT_BODY_TEXT_SMALL, views::style::STYLE_PRIMARY);
-  icon_view->SetImage(CreateVectorIconWithBadge(
-      *icon, GetLayoutConstant(LOCATION_BAR_ICON_SIZE), icon_color, badge));
-  return icon_view;
-}  // namespace
-
 enum class LayoutRowType {
   DEFAULT,
   INDENTED,
@@ -290,17 +230,45 @@
 
 void ContentSettingBubbleContents::ListItemContainer::AddItem(
     const ContentSettingBubbleModel::ListItem& item) {
-  std::unique_ptr<views::ImageView> item_icon =
-      std::make_unique<views::ImageView>();
+  // Padding for list items and icons.
+  static constexpr gfx::Insets kTitleDescriptionListItemInset(3, 0, 13, 0);
 
-  auto item_contents =
-      item.has_link
-          ? ConstructLinkItemContents(item.title, parent_)
-          : ConstructTitleDescriptionItemContents(item.title, item.description);
+  auto item_icon = std::make_unique<views::ImageView>();
   if (item.image) {
-    item_icon =
-        ConstructItemIcon(item.image, item.has_blocked_badge ? kBlockedBadgeIcon
-                                                             : gfx::kNoneIcon);
+    item_icon->SetBorder(
+        views::CreateEmptyBorder(kTitleDescriptionListItemInset));
+    const SkColor icon_color = views::style::GetColor(
+        *item_icon, CONTEXT_BODY_TEXT_SMALL, views::style::STYLE_PRIMARY);
+    item_icon->SetImage(CreateVectorIconWithBadge(
+        *item.image, GetLayoutConstant(LOCATION_BAR_ICON_SIZE), icon_color,
+        item.has_blocked_badge ? kBlockedBadgeIcon : gfx::kNoneIcon));
+  }
+
+  std::unique_ptr<views::View> item_contents;
+  if (item.has_link) {
+    auto link = std::make_unique<views::Link>(item.title);
+    link->SetElideBehavior(gfx::ELIDE_MIDDLE);
+    link->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+    link->set_listener(parent_);
+    item_contents = std::move(link);
+  } else {
+    item_contents->SetBorder(
+        views::CreateEmptyBorder(kTitleDescriptionListItemInset));
+    item_contents->SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::Orientation::kVertical));
+    const auto add_label = [&item_contents](const base::string16& string,
+                                            int style) {
+      if (!string.empty()) {
+        auto label = std::make_unique<views::Label>(
+            string, views::style::CONTEXT_LABEL, style,
+            gfx::DirectionalityMode::DIRECTIONALITY_FROM_UI);
+        label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+        label->SetAllowCharacterBreak(true);
+        item_contents->AddChildView(std::move(label));
+      }
+    };
+    add_label(item.title, views::style::STYLE_PRIMARY);
+    add_label(item.description, views::style::STYLE_DISABLED);
   }
 
   list_item_views_.push_back(AddNewRowToLayout(
@@ -381,6 +349,8 @@
   auto* scroll_view = views::ScrollView::GetScrollViewForContents(this);
   DCHECK(scroll_view);
   if (!scroll_view->is_bounded()) {
+    // Display a maximum of 4 visible items in a list before scrolling.
+    static constexpr int kMaxVisibleListItems = 4;
     scroll_view->ClipHeightTo(
         0, std::max(row.first->GetPreferredSize().height(),
                     row.second->GetPreferredSize().height()) *
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc
index 0043bf8..dfd5cc57 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -217,11 +217,13 @@
 }
 
 void DeviceChooserContentView::OnOptionsInitialized() {
+  is_initialized_ = true;
   table_view_->OnModelChanged();
   UpdateTableView();
 }
 
 void DeviceChooserContentView::OnOptionAdded(size_t index) {
+  is_initialized_ = true;
   table_view_->OnItemsAdded(base::checked_cast<int>(index), 1);
   UpdateTableView();
 }
@@ -353,10 +355,17 @@
 
 void DeviceChooserContentView::UpdateTableView() {
   bool has_options = adapter_enabled_ && RowCount() > 0;
+  if (!is_initialized_ && GetWidget() &&
+      GetWidget()->GetFocusManager()->GetFocusedView()) {
+    is_initialized_ = true;  // Can show no_options_view_ after initial focus.
+  }
   table_parent_->SetVisible(has_options);
   table_view_->SetEnabled(has_options &&
                           !chooser_controller_->TableViewAlwaysDisabled());
-  no_options_view_->SetVisible(!has_options && adapter_enabled_);
+  // Do not set to visible until initialization is complete, in order to prevent
+  // message from briefly flashing and being read by screen reader.
+  no_options_view_->SetVisible(!has_options && adapter_enabled_ &&
+                               is_initialized_);
   adapter_off_view_->SetVisible(!adapter_enabled_);
 }
 
diff --git a/chrome/browser/ui/views/device_chooser_content_view.h b/chrome/browser/ui/views/device_chooser_content_view.h
index 7852a14..5bd6564 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.h
+++ b/chrome/browser/ui/views/device_chooser_content_view.h
@@ -90,6 +90,8 @@
   views::View* adapter_off_view_ = nullptr;
   BluetoothStatusContainer* bluetooth_status_container_ = nullptr;
 
+  bool is_initialized_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(DeviceChooserContentView);
 };
 
diff --git a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
index cc6a8f1..a2eb9300 100644
--- a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
@@ -104,13 +104,21 @@
   bool IsDeviceSelected() { return !table_view()->selection_model().empty(); }
 
   void ExpectNoDevices() {
-    EXPECT_TRUE(no_options_view()->GetVisible());
     EXPECT_EQ(0, table_view()->GetRowCount());
     // The table should be disabled since there are no (real) options.
     EXPECT_FALSE(table_parent()->GetVisible());
     EXPECT_FALSE(table_view()->GetEnabled());
     EXPECT_FALSE(IsDeviceSelected());
   }
+  void ExpectNoDevicesWithMessageVisible() {
+    EXPECT_TRUE(no_options_view()->GetVisible());
+    ExpectNoDevices();
+  }
+
+  void ExpectNoDevicesWithMessageHidden() {
+    EXPECT_FALSE(no_options_view()->GetVisible());
+    ExpectNoDevices();
+  }
 
  protected:
   std::unique_ptr<views::View> extra_views_container_;
@@ -125,8 +133,7 @@
 
 TEST_F(DeviceChooserContentViewTest, InitialState) {
   EXPECT_CALL(table_observer(), OnSelectionChanged()).Times(0);
-
-  ExpectNoDevices();
+  ExpectNoDevicesWithMessageHidden();
   EXPECT_FALSE(adapter_off_view()->GetVisible());
   EXPECT_FALSE(throbber()->GetVisible());
   EXPECT_FALSE(scanning_label()->GetVisible());
@@ -170,7 +177,7 @@
   controller()->RemoveDevice(1);
   controller()->RemoveDevice(0);
   // Should be back to the initial state.
-  ExpectNoDevices();
+  ExpectNoDevicesWithMessageVisible();
 }
 
 TEST_F(DeviceChooserContentViewTest, UpdateOption) {
@@ -219,7 +226,7 @@
   controller()->RemoveDevice(0);
   controller()->SetBluetoothStatus(
       FakeBluetoothChooserController::BluetoothStatus::IDLE);
-  ExpectNoDevices();
+  ExpectNoDevicesWithMessageVisible();
   EXPECT_FALSE(adapter_off_view()->GetVisible());
   EXPECT_FALSE(throbber()->GetVisible());
   EXPECT_FALSE(scanning_label()->GetVisible());
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index 797bd3f9..1d5db1d2 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -335,10 +335,6 @@
   UpdateColorsFromTheme();
 }
 
-void DownloadShelfView::LinkClicked(views::Link* source, int event_flags) {
-  chrome::ShowDownloads(browser_);
-}
-
 void DownloadShelfView::ButtonPressed(
     views::Button* button, const ui::Event& event) {
   if (button == close_button_)
diff --git a/chrome/browser/ui/views/download/download_shelf_view.h b/chrome/browser/ui/views/download/download_shelf_view.h
index 8352a02..b40d753 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.h
+++ b/chrome/browser/ui/views/download/download_shelf_view.h
@@ -16,7 +16,6 @@
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/animation/animation_delegate_views.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/mouse_watcher.h"
 
 class Browser;
@@ -41,7 +40,6 @@
                           public views::AnimationDelegateViews,
                           public DownloadShelf,
                           public views::ButtonListener,
-                          public views::LinkListener,
                           public views::MouseWatcherListener {
  public:
   DownloadShelfView(Browser* browser, BrowserView* parent);
@@ -64,10 +62,6 @@
   void AnimationProgressed(const gfx::Animation* animation) override;
   void AnimationEnded(const gfx::Animation* animation) override;
 
-  // views::LinkListener.
-  // Invoked when the user clicks the 'show all downloads' link button.
-  void LinkClicked(views::Link* source, int event_flags) override;
-
   // views::ButtonListener:
   // Invoked when the user clicks the close button. Asks the browser to
   // hide the download shelf.
diff --git a/chrome/browser/ui/views/extensions/expandable_container_view.cc b/chrome/browser/ui/views/extensions/expandable_container_view.cc
index 602dd077..ef750d566 100644
--- a/chrome/browser/ui/views/extensions/expandable_container_view.cc
+++ b/chrome/browser/ui/views/extensions/expandable_container_view.cc
@@ -52,8 +52,7 @@
 
 ExpandableContainerView::ExpandableContainerView(
     const std::vector<base::string16>& details,
-    int available_width)
-    : details_view_(nullptr), details_link_(nullptr) {
+    int available_width) {
   DCHECK(!details.empty());
 
   views::GridLayout* layout =
@@ -78,7 +77,7 @@
   details_link_ = layout->AddView(std::move(details_link));
 }
 
-ExpandableContainerView::~ExpandableContainerView() {}
+ExpandableContainerView::~ExpandableContainerView() = default;
 
 void ExpandableContainerView::LinkClicked(views::Link* source,
                                           int event_flags) {
diff --git a/chrome/browser/ui/views/extensions/expandable_container_view.h b/chrome/browser/ui/views/extensions/expandable_container_view.h
index e1692e95..1577392 100644
--- a/chrome/browser/ui/views/extensions/expandable_container_view.h
+++ b/chrome/browser/ui/views/extensions/expandable_container_view.h
@@ -55,11 +55,11 @@
   void ToggleDetailLevel();
 
   // The view that expands or collapses when |details_link_| is clicked.
-  DetailsView* details_view_;
+  DetailsView* details_view_ = nullptr;
 
   // The 'Show Details' link, which changes to 'Hide Details' when the details
   // section is expanded.
-  views::Link* details_link_;
+  views::Link* details_link_ = nullptr;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXPANDABLE_CONTAINER_VIEW_H_
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
index 04260d3..ee0309d 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -186,13 +186,6 @@
       {prompt->GetPermissionsHeading(), std::move(permissions_view)});
 }
 
-std::unique_ptr<views::Link> CreatePromptLink(views::LinkListener* listener) {
-  auto store_link = std::make_unique<views::Link>(
-      l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK));
-  store_link->set_listener(listener);
-  return store_link;
-}
-
 }  // namespace
 
 ExtensionInstallDialogView::ExtensionInstallDialogView(
@@ -212,8 +205,12 @@
 
   DialogDelegate::set_default_button(ui::DIALOG_BUTTON_CANCEL);
   DialogDelegate::set_draggable(true);
-  if (prompt_->has_webstore_data())
-    DialogDelegate::SetExtraView(CreatePromptLink(this));
+  if (prompt_->has_webstore_data()) {
+    auto store_link = std::make_unique<views::Link>(
+        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK));
+    store_link->set_listener(this);
+    DialogDelegate::SetExtraView(std::move(store_link));
+  }
   DialogDelegate::set_button_label(ui::DIALOG_BUTTON_OK,
                                    prompt_->GetAcceptButtonLabel());
   DialogDelegate::set_button_label(ui::DIALOG_BUTTON_CANCEL,
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
index 8d195e2..9cadb5e 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -23,10 +23,6 @@
 class PageNavigator;
 }
 
-namespace views {
-class Link;
-}
-
 // Modal dialog that shows when the user attempts to install an extension. Also
 // shown if the extension is already installed but needs additional permissions.
 // Not a normal "bubble" despite being a subclass of BubbleDialogDelegateView.
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index 55f60b67..2917055 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
@@ -320,9 +321,6 @@
 
   BubbleReference bubble_reference_;
 
-  // The shortcut to open the manage shortcuts page.
-  views::Link* manage_shortcut_;
-
   Browser* const browser_;
   const scoped_refptr<const extensions::Extension> extension_;
   const gfx::ImageSkia icon_;
@@ -340,7 +338,6 @@
                                    ? views::BubbleBorder::TOP_LEFT
                                    : views::BubbleBorder::TOP_RIGHT),
       bubble_reference_(bubble_reference),
-      manage_shortcut_(nullptr),
       browser_(browser),
       extension_(extension),
       icon_(MakeIconFromBitmap(icon)) {
@@ -432,11 +429,10 @@
   }
 
   if (ShouldShowKeybinding(extension_.get(), browser_)) {
-    manage_shortcut_ = new views::Link(
-        l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS));
-    manage_shortcut_->set_listener(this);
-    manage_shortcut_->SetUnderline(false);
-    AddChildView(manage_shortcut_);
+    auto* manage_shortcut = AddChildView(std::make_unique<views::Link>(
+        l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS)));
+    manage_shortcut->set_listener(this);
+    manage_shortcut->SetUnderline(false);
   }
 
   if (ShouldShowHowToManage(extension_.get(), browser_)) {
@@ -456,12 +452,9 @@
 
 void ExtensionInstalledBubbleView::LinkClicked(views::Link* source,
                                                int event_flags) {
-  DCHECK_EQ(manage_shortcut_, source);
-
-  std::string configure_url = chrome::kChromeUIExtensionsURL;
-  configure_url += chrome::kExtensionConfigureCommandsSubPage;
-  NavigateParams params(
-      GetSingletonTabNavigateParams(browser_, GURL(configure_url)));
+  const GURL kUrl(base::StrCat({chrome::kChromeUIExtensionsURL,
+                                chrome::kExtensionConfigureCommandsSubPage}));
+  NavigateParams params = GetSingletonTabNavigateParams(browser_, kUrl);
   Navigate(&params);
   CloseBubble(BUBBLE_CLOSE_NAVIGATED);
 }
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc
index 3a483e8..f9bd66f 100644
--- a/chrome/browser/ui/views/first_run_dialog.cc
+++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -42,20 +42,11 @@
   if (enabled)
     breakpad::InitCrashReporter(std::string());
 #elif defined(OS_LINUX)
-  if (!crash_reporter::IsCrashpadEnabled() && enabled) {
+  if (!crash_reporter::IsCrashpadEnabled() && enabled)
     breakpad::InitCrashReporter(std::string());
-  }
 #endif
 }
 
-std::unique_ptr<views::View> CreateLearnMoreLink(
-    views::LinkListener* listener) {
-  auto link =
-      std::make_unique<views::Link>(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
-  link->set_listener(listener);
-  return link;
-}
-
 }  // namespace
 
 namespace first_run {
@@ -78,7 +69,9 @@
 
 FirstRunDialog::FirstRunDialog(Profile* profile) : profile_(profile) {
   DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK);
-  DialogDelegate::SetExtraView(CreateLearnMoreLink(this));
+  DialogDelegate::SetExtraView(
+      std::make_unique<views::Link>(l10n_util::GetStringUTF16(IDS_LEARN_MORE)))
+      ->set_listener(this);
 
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
       views::TEXT, views::TEXT));
diff --git a/chrome/browser/ui/views/first_run_dialog.h b/chrome/browser/ui/views/first_run_dialog.h
index 5e47ad40..76f48e4 100644
--- a/chrome/browser/ui/views/first_run_dialog.h
+++ b/chrome/browser/ui/views/first_run_dialog.h
@@ -14,7 +14,6 @@
 
 namespace views {
 class Checkbox;
-class Link;
 }
 
 class FirstRunDialog : public views::DialogDelegateView,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index c1bdc25c..d17b8f8 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -162,10 +162,8 @@
 
 void BrowserNonClientFrameView::UpdateFrameColor() {
   // Only web-app windows support dynamic frame colors set by HTML meta tags.
-  if (!web_app_frame_toolbar_)
-    return;
-  web_app_frame_toolbar_->UpdateCaptionColors();
-  SchedulePaint();
+  if (web_app_frame_toolbar_)
+    web_app_frame_toolbar_->UpdateCaptionColors();
 }
 
 SkColor BrowserNonClientFrameView::GetToolbarTopSeparatorColor() const {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 1c541ea2..8d99f6d 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -165,8 +165,6 @@
     SetUpForWebApp();
 
   browser_view()->immersive_mode_controller()->AddObserver(this);
-
-  UpdateFrameColor();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -226,30 +224,7 @@
 }
 
 void BrowserNonClientFrameViewAsh::UpdateFrameColor() {
-  aura::Window* window = frame()->GetNativeWindow();
-  base::Optional<SkColor> active_color, inactive_color;
-  if (!UsePackagedAppHeaderStyle(browser_view()->browser())) {
-    active_color = GetFrameColor(BrowserFrameActiveState::kActive);
-    inactive_color = GetFrameColor(BrowserFrameActiveState::kInactive);
-  } else if (browser_view()->IsBrowserTypeWebApp()) {
-    active_color = browser_view()->browser()->app_controller()->GetThemeColor();
-  } else if (!browser_view()->browser()->deprecated_is_app()) {
-    // TODO(crbug.com/836128): Remove when System Web Apps flag is removed, as
-    // the above web-app branch will render the theme color.
-    active_color = SK_ColorWHITE;
-  }
-
-  if (active_color) {
-    window->SetProperty(ash::kFrameActiveColorKey, *active_color);
-    window->SetProperty(ash::kFrameInactiveColorKey,
-                        inactive_color.value_or(*active_color));
-  } else {
-    window->ClearProperty(ash::kFrameActiveColorKey);
-    window->ClearProperty(ash::kFrameInactiveColorKey);
-  }
-
-  frame_header_->UpdateFrameColors();
-
+  OnUpdateFrameColor();
   BrowserNonClientFrameView::UpdateFrameColor();
 }
 
@@ -433,7 +408,7 @@
 }
 
 void BrowserNonClientFrameViewAsh::OnThemeChanged() {
-  UpdateFrameColor();
+  OnUpdateFrameColor();
   BrowserNonClientFrameView::OnThemeChanged();
 }
 
@@ -715,11 +690,8 @@
     return;
 
   // Add the container for extra web app buttons (e.g app menu button).
-  set_web_app_frame_toolbar(new WebAppFrameToolbarView(
-      frame(), browser_view(),
-      GetCaptionColor(BrowserFrameActiveState::kActive),
-      GetCaptionColor(BrowserFrameActiveState::kInactive)));
-  AddChildView(web_app_frame_toolbar());
+  set_web_app_frame_toolbar(AddChildView(
+      std::make_unique<WebAppFrameToolbarView>(frame(), browser_view())));
 }
 
 void BrowserNonClientFrameViewAsh::UpdateTopViewInset() {
@@ -791,6 +763,32 @@
   return GetFrameWindow()->GetProperty(ash::kIsShowingInOverviewKey);
 }
 
+void BrowserNonClientFrameViewAsh::OnUpdateFrameColor() {
+  aura::Window* window = frame()->GetNativeWindow();
+  base::Optional<SkColor> active_color, inactive_color;
+  if (!UsePackagedAppHeaderStyle(browser_view()->browser())) {
+    active_color = GetFrameColor(BrowserFrameActiveState::kActive);
+    inactive_color = GetFrameColor(BrowserFrameActiveState::kInactive);
+  } else if (browser_view()->IsBrowserTypeWebApp()) {
+    active_color = browser_view()->browser()->app_controller()->GetThemeColor();
+  } else if (!browser_view()->browser()->deprecated_is_app()) {
+    // TODO(crbug.com/836128): Remove when System Web Apps flag is removed, as
+    // the above web-app branch will render the theme color.
+    active_color = SK_ColorWHITE;
+  }
+
+  if (active_color) {
+    window->SetProperty(ash::kFrameActiveColorKey, *active_color);
+    window->SetProperty(ash::kFrameInactiveColorKey,
+                        inactive_color.value_or(*active_color));
+  } else {
+    window->ClearProperty(ash::kFrameActiveColorKey);
+    window->ClearProperty(ash::kFrameInactiveColorKey);
+  }
+
+  frame_header_->UpdateFrameColors();
+}
+
 const aura::Window* BrowserNonClientFrameViewAsh::GetFrameWindow() const {
   return const_cast<BrowserNonClientFrameViewAsh*>(this)->GetFrameWindow();
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index 856aa13..5de4612 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -196,6 +196,9 @@
   // Returns whether this window is currently in the overview list.
   bool IsInOverviewMode() const;
 
+  // Called any time the frame color may have changed.
+  void OnUpdateFrameColor();
+
   // Returns the top level aura::Window for this browser window.
   const aura::Window* GetFrameWindow() const;
   aura::Window* GetFrameWindow();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 4695525..cae9d13 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -833,7 +833,7 @@
   AppMenu* GetAppMenu() { return web_app_menu_button_->app_menu(); }
 
   SkColor GetActiveColor() const {
-    return web_app_frame_toolbar_->active_color_;
+    return web_app_frame_toolbar_->active_foreground_color_;
   }
 
   bool GetPaintingAsActive() const {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
index dc5c592..1c24e82 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -70,11 +70,8 @@
 
   if (browser_view->IsBrowserTypeWebApp()) {
     if (browser_view->browser()->app_controller()->HasTitlebarToolbar()) {
-      set_web_app_frame_toolbar(
-          AddChildView(std::make_unique<WebAppFrameToolbarView>(
-              frame, browser_view,
-              GetCaptionColor(BrowserFrameActiveState::kActive),
-              GetCaptionColor(BrowserFrameActiveState::kInactive))));
+      set_web_app_frame_toolbar(AddChildView(
+          std::make_unique<WebAppFrameToolbarView>(frame, browser_view)));
     }
 
     // The window title appears above the web app frame toolbar (if present),
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 1f6ed24..351f21cb 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -110,14 +110,8 @@
   web_app::AppBrowserController* controller =
       browser_view->browser()->app_controller();
   if (controller && controller->HasTitlebarToolbar()) {
-    // TODO(alancutter): Avoid snapshotting GetCaptionColor() values here and
-    // call it on demand in WebAppFrameToolbarView::UpdateIconsColor() via a
-    // delegate interface.
-    set_web_app_frame_toolbar(
-        AddChildView(std::make_unique<WebAppFrameToolbarView>(
-            frame, browser_view,
-            GetCaptionColor(BrowserFrameActiveState::kActive),
-            GetCaptionColor(BrowserFrameActiveState::kInactive))));
+    set_web_app_frame_toolbar(AddChildView(
+        std::make_unique<WebAppFrameToolbarView>(frame, browser_view)));
   }
 
   // The window title appears above the web app frame toolbar (if present),
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 5cb0f2d..98cf402b 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -177,11 +177,8 @@
   web_app::AppBrowserController* controller =
       browser_view()->browser()->app_controller();
   if (controller && controller->HasTitlebarToolbar()) {
-    set_web_app_frame_toolbar(
-        AddChildView(std::make_unique<WebAppFrameToolbarView>(
-            frame(), browser_view(),
-            GetCaptionColor(BrowserFrameActiveState::kActive),
-            GetCaptionColor(BrowserFrameActiveState::kInactive))));
+    set_web_app_frame_toolbar(AddChildView(
+        std::make_unique<WebAppFrameToolbarView>(frame(), browser_view())));
   }
 
   // The window title appears above the web app frame toolbar (if present),
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
index 040bec6..c10c9f1 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
@@ -29,19 +29,12 @@
 using base::UserMetricsAction;
 
 namespace {
+
 // Singleton instance of the cookie bubble. The cookie bubble can only be
 // shown on the active browser window, so there is no case in which it will be
 // shown twice at the same time.
 static CookieControlsBubbleView* g_instance;
 
-std::unique_ptr<views::Link> CreateNotWorkingLink(
-    views::LinkListener* listener) {
-  auto link = std::make_unique<views::Link>(
-      l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE));
-  link->set_listener(listener);
-  return link;
-}
-
 std::unique_ptr<views::TooltipIcon> CreateInfoIcon() {
   auto explanation_tooltip = std::make_unique<views::TooltipIcon>(
       l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_HELP));
@@ -142,7 +135,10 @@
     text_->SetVisible(true);
     text_->SetText(
         l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE));
-    extra_view_ = SetExtraView(CreateNotWorkingLink(this));
+    auto link = std::make_unique<views::Link>(
+        l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE));
+    link->set_listener(this);
+    extra_view_ = SetExtraView(std::move(link));
     blocked_cookies_.reset();
   } else {
     DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
index 8810eb21..778ce6b 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
@@ -21,7 +21,6 @@
 namespace views {
 class ImageView;
 class Label;
-class Link;
 }  // namespace views
 
 // View used to display the cookie controls ui.
@@ -85,7 +84,7 @@
   views::ImageView* header_view_ = nullptr;
   views::Label* text_ = nullptr;
   views::View* extra_view_ = nullptr;
-  views::Link* show_cookies_link_ = nullptr;
+  views::View* show_cookies_link_ = nullptr;
 
   ScopedObserver<CookieControlsController, CookieControlsView> observer_{this};
 
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
index 510b6d6..768b0fa 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -138,6 +138,10 @@
     return title_label_->font_list().GetExpectedTextWidth(kMinCharacters);
   }
 
+  SkColor GetLocationColor() const {
+    return location_label_->GetEnabledColor();
+  }
+
   // views::View:
   gfx::Size GetMinimumSize() const override {
     return gfx::Size(GetMinimumWidth(), GetPreferredSize().height());
@@ -350,8 +354,11 @@
 }
 
 SkColor CustomTabBarView::GetIconLabelBubbleSurroundingForegroundColor() const {
-  return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+  return title_origin_view_->GetLocationColor();
+}
+
+SkColor CustomTabBarView::GetIconLabelBubbleBackgroundColor() const {
+  return background_color_;
 }
 
 content::WebContents* CustomTabBarView::GetWebContents() {
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
index 7669233..bd41350 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
@@ -63,6 +63,7 @@
 
   // IconLabelBubbleView::Delegate:
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override;
+  SkColor GetIconLabelBubbleBackgroundColor() const override;
 
   // LocationIconView::Delegate:
   content::WebContents* GetWebContents() override;
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 24f6b8d..7837e4b 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -16,7 +16,6 @@
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/canvas.h"
-#include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/scoped_canvas.h"
@@ -65,9 +64,12 @@
 }
 
 void IconLabelBubbleView::SeparatorView::OnPaint(gfx::Canvas* canvas) {
-  const SkColor background_color = owner_->GetParentBackgroundColor();
-  const SkColor separator_color =
-      SkColorSetA(color_utils::GetColorWithMaxContrast(background_color), 0x69);
+  // This uses the surrounding context as the base color instead of
+  // IconLabelBubbleView::GetForegroundColor() so that if the
+  // IconLabelBubbleView has been emphasized (e.g. red text for a security
+  // error) the separator will still blend into the background.
+  const SkColor separator_color = SkColorSetA(
+      owner_->delegate_->GetIconLabelBubbleSurroundingForegroundColor(), 0x69);
   const float x = GetLocalBounds().right() -
                   owner_->GetEndPaddingWithSeparator() -
                   1.0f / canvas->image_scale();
@@ -75,6 +77,10 @@
                    gfx::PointF(x, GetLocalBounds().bottom()), separator_color);
 }
 
+void IconLabelBubbleView::SeparatorView::OnThemeChanged() {
+  SchedulePaint();
+}
+
 void IconLabelBubbleView::SeparatorView::UpdateOpacity() {
   if (!GetVisible())
     return;
@@ -181,10 +187,6 @@
   separator_view_->UpdateOpacity();
 }
 
-void IconLabelBubbleView::SetImage(const gfx::ImageSkia& image_skia) {
-  LabelButton::SetImage(STATE_NORMAL, image_skia);
-}
-
 void IconLabelBubbleView::SetFontList(const gfx::FontList& font_list) {
   label()->SetFontList(font_list);
 }
@@ -193,11 +195,6 @@
   return delegate_->GetIconLabelBubbleSurroundingForegroundColor();
 }
 
-SkColor IconLabelBubbleView::GetParentBackgroundColor() const {
-  return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_TextfieldDefaultBackground);
-}
-
 bool IconLabelBubbleView::ShouldShowSeparator() const {
   return ShouldShowLabel();
 }
@@ -308,7 +305,7 @@
   label()->SetBackground(nullptr);
 
   SetEnabledTextColors(GetForegroundColor());
-  label()->SetBackgroundColor(GetParentBackgroundColor());
+  label()->SetBackgroundColor(delegate_->GetIconLabelBubbleBackgroundColor());
   SchedulePaint();
 }
 
@@ -397,6 +394,10 @@
     PreferredSizeChanged();
 }
 
+void IconLabelBubbleView::SetImage(const gfx::ImageSkia& image_skia) {
+  LabelButton::SetImage(STATE_NORMAL, image_skia);
+}
+
 gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int label_width) const {
   gfx::Size image_size = image()->GetPreferredSize();
   image_size.Enlarge(GetInsets().left() + GetWidthBetweenIconAndSeparator() +
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
index 037f22bc..46857fd 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -50,12 +50,15 @@
    public:
     // Returns the foreground color of items around the IconLabelBubbleView,
     // e.g. nearby text items.  By default, the IconLabelBubbleView will use
-    // this as its foreground color and ink drop base color.
+    // this as its foreground color, separator, and ink drop base color.
     virtual SkColor GetIconLabelBubbleSurroundingForegroundColor() const = 0;
 
     // Returns the base color for ink drops.  If not overridden, this returns
     // GetIconLabelBubbleSurroundingForegroundColor().
     virtual SkColor GetIconLabelBubbleInkDropColor() const;
+
+    // Returns the background color behind the IconLabelBubbleView.
+    virtual SkColor GetIconLabelBubbleBackgroundColor() const = 0;
   };
 
   IconLabelBubbleView(const gfx::FontList& font_list, Delegate* delegate);
@@ -69,15 +72,11 @@
   virtual bool ShouldShowLabel() const;
 
   void SetLabel(const base::string16& label);
-  void SetImage(const gfx::ImageSkia& image);
   void SetFontList(const gfx::FontList& font_list);
 
   const views::ImageView* GetImageView() const { return image(); }
   views::ImageView* GetImageView() { return image(); }
 
-  // Returns the color of the IconLabelBubbleView's surrounding context.
-  SkColor GetParentBackgroundColor() const;
-
   // Exposed for testing.
   views::View* separator_view() const { return separator_view_; }
 
@@ -142,6 +141,8 @@
 
   const gfx::FontList& font_list() const { return label()->font_list(); }
 
+  void SetImage(const gfx::ImageSkia& image);
+
   gfx::Size GetSizeForLabelWidth(int label_width) const;
 
   // Set up for icons that animate their labels in. Animating out is initiated
@@ -189,6 +190,7 @@
 
     // views::View:
     void OnPaint(gfx::Canvas* canvas) override;
+    void OnThemeChanged() override;
 
     // Updates the opacity based on the ink drop's state.
     void UpdateOpacity();
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
index a1fce1bd..4ec717b 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
@@ -134,6 +134,9 @@
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override {
     return kTestColor;
   }
+  SkColor GetIconLabelBubbleBackgroundColor() const override {
+    return kTestColor;
+  }
 };
 
 class IconLabelBubbleViewTest : public IconLabelBubbleViewTestBase {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 3e12d48a..6cde51f 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -197,20 +197,18 @@
 
   RefreshBackground();
 
-  ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
-
   // Initialize the inline autocomplete view which is visible only when IME is
   // turned on.  Use the same font with the omnibox and highlighted background.
   auto ime_inline_autocomplete_view = std::make_unique<views::Label>(
       base::string16(), views::Label::CustomFont{font_list});
   ime_inline_autocomplete_view->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   ime_inline_autocomplete_view->SetAutoColorReadabilityEnabled(false);
-  ime_inline_autocomplete_view->SetBackground(
-      views::CreateSolidBackground(native_theme->GetSystemColor(
-          ui::NativeTheme::ColorId::
-              kColorId_TextfieldSelectionBackgroundFocused)));
-  ime_inline_autocomplete_view->SetEnabledColor(native_theme->GetSystemColor(
-      ui::NativeTheme::ColorId::kColorId_TextfieldSelectionColor));
+  ime_inline_autocomplete_view->SetBackground(views::CreateSolidBackground(
+      GetOmniboxColor(GetThemeProvider(), OmniboxPart::LOCATION_BAR_BACKGROUND,
+                      OmniboxPartState::SELECTED)));
+  ime_inline_autocomplete_view->SetEnabledColor(GetOmniboxColor(
+      GetThemeProvider(), OmniboxPart::LOCATION_BAR_TEXT_DEFAULT,
+      OmniboxPartState::SELECTED));
   ime_inline_autocomplete_view->SetVisible(false);
   ime_inline_autocomplete_view_ =
       AddChildView(std::move(ime_inline_autocomplete_view));
@@ -430,7 +428,7 @@
 }
 
 void LocationBarView::OnKeywordFaviconFetched(const gfx::Image& icon) {
-  selected_keyword_view_->SetImage(icon.AsImageSkia());
+  selected_keyword_view_->SetCustomImage(icon.AsImageSkia());
 }
 
 void LocationBarView::Layout() {
@@ -508,7 +506,7 @@
         gfx::Image image =
             extensions::OmniboxAPI::Get(profile_)->GetOmniboxIcon(
                 template_url->GetExtensionId());
-        selected_keyword_view_->SetImage(image.AsImageSkia());
+        selected_keyword_view_->SetCustomImage(image.AsImageSkia());
       } else if (template_url && template_url->type() == TemplateURL::NORMAL &&
                  OmniboxFieldTrial::IsExperimentalKeywordModeEnabled()) {
         gfx::Image image =
@@ -520,7 +518,7 @@
                     base::BindOnce(&LocationBarView::OnKeywordFaviconFetched,
                                    base::Unretained(this)));
         if (!image.IsEmpty())
-          selected_keyword_view_->SetImage(image.AsImageSkia());
+          selected_keyword_view_->SetCustomImage(image.AsImageSkia());
         else
           selected_keyword_view_->ResetImage();
       } else {
@@ -670,8 +668,11 @@
 }
 
 SkColor LocationBarView::GetIconLabelBubbleSurroundingForegroundColor() const {
-  return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+  return GetColor(OmniboxPart::LOCATION_BAR_TEXT_DEFAULT);
+}
+
+SkColor LocationBarView::GetIconLabelBubbleBackgroundColor() const {
+  return GetColor(OmniboxPart::LOCATION_BAR_BACKGROUND);
 }
 
 content::WebContents* LocationBarView::GetContentSettingWebContents() {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index c8c1c29..baeba40 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -189,6 +189,7 @@
 
   // IconLabelBubbleView::Delegate:
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override;
+  SkColor GetIconLabelBubbleBackgroundColor() const override;
 
   // ContentSettingImageView::Delegate:
   content::WebContents* GetContentSettingWebContents() override;
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view_unittest.cc b/chrome/browser/ui/views/location_bar/location_icon_view_unittest.cc
index d528bae..3454a9d 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view_unittest.cc
@@ -22,13 +22,16 @@
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override {
     return SK_ColorBLACK;
   }
+  SkColor GetIconLabelBubbleBackgroundColor() const override {
+    return SK_ColorWHITE;
+  }
 
   // LocationIconView::Delegate:
   content::WebContents* GetWebContents() override { return nullptr; }
   bool IsEditingOrEmpty() const override { return is_editing_or_empty_; }
   SkColor GetSecurityChipColor(
       security_state::SecurityLevel security_level) const override {
-    return SK_ColorWHITE;
+    return GetIconLabelBubbleSurroundingForegroundColor();
   }
   bool ShowPageInfoDialog() override { return false; }
   const LocationBarModel* GetLocationBarModel() const override {
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
index 6d501acf..323247d 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -34,10 +34,16 @@
 
 SelectedKeywordView::~SelectedKeywordView() {}
 
+void SelectedKeywordView::SetCustomImage(const gfx::ImageSkia& image) {
+  IconLabelBubbleView::SetImage(image);
+  using_custom_image_ = true;
+}
+
 void SelectedKeywordView::ResetImage() {
-  SetImage(gfx::CreateVectorIcon(vector_icons::kSearchIcon,
-                                 GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
-                                 GetForegroundColor()));
+  IconLabelBubbleView::SetImage(gfx::CreateVectorIcon(
+      vector_icons::kSearchIcon, GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
+      GetForegroundColor()));
+  using_custom_image_ = false;
 }
 
 void SelectedKeywordView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
@@ -58,6 +64,12 @@
   return GetSizeForLabelWidth(0);
 }
 
+void SelectedKeywordView::OnThemeChanged() {
+  IconLabelBubbleView::OnThemeChanged();
+  if (!using_custom_image_)
+    ResetImage();
+}
+
 void SelectedKeywordView::SetKeyword(const base::string16& keyword) {
   if (keyword_ != keyword) {
     keyword_ = keyword;
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.h b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
index cf4c773..21fdedf 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.h
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
@@ -29,13 +29,16 @@
                       Profile* profile);
   ~SelectedKeywordView() override;
 
-  // Resets the icon for this chip to its default (it may have been changed
-  // for an extension).
+  // Sets the icon for this chip to |image|.
+  void SetCustomImage(const gfx::ImageSkia& image);
+
+  // Resets the icon for this chip to its default.
   void ResetImage();
 
   // IconLabelBubbleView:
   gfx::Size CalculatePreferredSize() const override;
   gfx::Size GetMinimumSize() const override;
+  void OnThemeChanged() override;
   SkColor GetForegroundColor() const override;
 
   // The current keyword, or an empty string if no keyword is displayed.
@@ -68,6 +71,9 @@
 
   Profile* profile_;
 
+  // True when the chip icon has been changed via SetCustomImage().
+  bool using_custom_image_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(SelectedKeywordView);
 };
 
diff --git a/chrome/browser/ui/views/network_profile_bubble_view.cc b/chrome/browser/ui/views/network_profile_bubble_view.cc
index e97881b..09bd7d3 100644
--- a/chrome/browser/ui/views/network_profile_bubble_view.cc
+++ b/chrome/browser/ui/views/network_profile_bubble_view.cc
@@ -24,17 +24,6 @@
 
 namespace {
 
-// Bubble layout constants.
-const int kNotificationBubbleWidth = 250;
-
-std::unique_ptr<views::View> CreateLearnMoreLink(
-    views::LinkListener* listener) {
-  auto learn_more =
-      std::make_unique<views::Link>(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
-  learn_more->set_listener(listener);
-  return learn_more;
-}
-
 class NetworkProfileBubbleView : public views::BubbleDialogDelegateView,
                                  public views::LinkListener {
  public:
@@ -69,7 +58,9 @@
       navigator_(navigator),
       profile_(profile) {
   DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK);
-  DialogDelegate::SetExtraView(CreateLearnMoreLink(this));
+  auto* learn_more = DialogDelegate::SetExtraView(
+      std::make_unique<views::Link>(l10n_util::GetStringUTF16(IDS_LEARN_MORE)));
+  learn_more->set_listener(this);
   chrome::RecordDialogCreation(
       chrome::DialogIdentifier::NETWORK_SHARE_PROFILE_WARNING);
 }
@@ -86,6 +77,7 @@
       l10n_util::GetStringFUTF16(IDS_PROFILE_ON_NETWORK_WARNING,
           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
   label->SetMultiLine(true);
+  constexpr int kNotificationBubbleWidth = 250;
   label->SizeToFit(kNotificationBubbleWidth);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   AddChildView(label);
@@ -101,15 +93,12 @@
                                            int event_flags) {
   NetworkProfileBubble::RecordUmaEvent(
       NetworkProfileBubble::METRIC_LEARN_MORE_CLICKED);
-  WindowOpenDisposition disposition =
-      ui::DispositionFromEventFlags(event_flags);
+  WindowOpenDisposition disposition = ui::DispositionFromEventFlags(
+      event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   content::OpenURLParams params(
       GURL("https://sites.google.com/a/chromium.org/dev/administrators/"
            "common-problems-and-solutions#network_profile"),
-      content::Referrer(), disposition == WindowOpenDisposition::CURRENT_TAB
-                               ? WindowOpenDisposition::NEW_FOREGROUND_TAB
-                               : disposition,
-      ui::PAGE_TRANSITION_LINK, false);
+      content::Referrer(), disposition, ui::PAGE_TRANSITION_LINK, false);
   navigator_->OpenURL(params);
 
   // If the user interacted with the bubble we don't reduce the number of
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index c149c10..3eb0c13 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -580,10 +580,6 @@
   }
 }
 
-void PageInfoBubbleView::LinkClicked(views::Link* source, int event_flags) {
-  HandleMoreInfoRequest(source);
-}
-
 gfx::Size PageInfoBubbleView::CalculatePreferredSize() const {
   if (header_ == nullptr && site_settings_view_ == nullptr) {
     return views::View::CalculatePreferredSize();
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
index d02ebb8..466f205 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -26,7 +26,6 @@
 #include "components/security_state/core/security_state.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/styled_label_listener.h"
@@ -53,7 +52,6 @@
 }  // namespace test
 
 namespace views {
-class Link;
 class View;
 }  // namespace views
 
@@ -62,7 +60,6 @@
                            public PermissionSelectorRowObserver,
                            public ChosenObjectViewObserver,
                            public views::ButtonListener,
-                           public views::LinkListener,
                            public views::StyledLabelListener,
                            public PageInfoUI {
  public:
@@ -139,9 +136,6 @@
   // views::ButtonListener:
   void ButtonPressed(views::Button* button, const ui::Event& event) override;
 
-  // views::LinkListener:
-  void LinkClicked(views::Link* source, int event_flags) override;
-
   // views::StyledLabelListener:
   void StyledLabelLinkClicked(views::StyledLabel* label,
                               const gfx::Range& range,
diff --git a/chrome/browser/ui/views/passwords/password_items_view.cc b/chrome/browser/ui/views/passwords/password_items_view.cc
index 970da2f..57a1add 100644
--- a/chrome/browser/ui/views/passwords/password_items_view.cc
+++ b/chrome/browser/ui/views/passwords/password_items_view.cc
@@ -28,7 +28,6 @@
 #include "ui/views/controls/editable_combobox/editable_combobox.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/style/typography.h"
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc
index 6117d481..487820bfd 100644
--- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc
@@ -355,7 +355,7 @@
   EXPECT_TRUE(styled_label);
 
   content::WebContentsAddedObserver web_contents_added_observer;
-  styled_label->LinkClicked(nullptr, 0);
+  styled_label->LinkClicked(nullptr, ui::EF_NONE);
   content::WebContents* new_tab_contents =
       web_contents_added_observer.GetWebContents();
 
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_browsertest.cc
index 0ef4dd8..ea48e7b8 100644
--- a/chrome/browser/ui/views/payments/payment_request_browsertest.cc
+++ b/chrome/browser/ui/views/payments/payment_request_browsertest.cc
@@ -429,7 +429,7 @@
   EXPECT_TRUE(styled_label);
   // The Link is the only child of the StyledLabel.
   content::WebContentsAddedObserver web_contents_added_observer;
-  styled_label->LinkClicked(nullptr, 0);
+  styled_label->LinkClicked(nullptr, ui::EF_NONE);
   content::WebContents* new_tab_contents =
       web_contents_added_observer.GetWebContents();
 
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index e955616..7c8fe816 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -588,10 +588,6 @@
   OnClick(button);
 }
 
-void ProfileMenuViewBase::LinkClicked(views::Link* link, int event_flags) {
-  OnClick(link);
-}
-
 void ProfileMenuViewBase::StyledLabelLinkClicked(views::StyledLabel* link,
                                                  const gfx::Range& range,
                                                  int event_flags) {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index fdd6e12..dc4d24f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -19,7 +19,6 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/style/typography.h"
@@ -40,8 +39,7 @@
 class ProfileMenuViewBase : public content::WebContentsDelegate,
                             public views::BubbleDialogDelegateView,
                             public views::ButtonListener,
-                            public views::StyledLabelListener,
-                            public views::LinkListener {
+                            public views::StyledLabelListener {
  public:
   // Enumeration of all actionable items in the profile menu.
   // These values are persisted to logs. Entries should not be renumbered and
@@ -235,9 +233,6 @@
   // views::ButtonListener:
   void ButtonPressed(views::Button* button, const ui::Event& event) final;
 
-  // views::LinkListener:
-  void LinkClicked(views::Link* link, int event_flags) final;
-
   // views::StyledLabelListener:
   void StyledLabelLinkClicked(views::StyledLabel* link,
                               const gfx::Range& range,
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 44e6fa5..b518d0563 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
@@ -71,11 +71,6 @@
   return "QRCodeGeneratorIconView";
 }
 
-SkColor QRCodeGeneratorIconView::GetForegroundColor() const {
-  return GetOmniboxColor(GetThemeProvider(),
-                         OmniboxPart::LOCATION_BAR_TEXT_DEFAULT);
-}
-
 base::string16 QRCodeGeneratorIconView::GetTextForTooltipAndAccessibleName()
     const {
   return l10n_util::GetStringUTF16(IDS_OMNIBOX_QRCODE_GENERATOR_ICON_TOOLTIP);
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 91f5512..cd4805f 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
@@ -25,7 +25,6 @@
   // PageActionIconView:
   views::BubbleDialogDelegateView* GetBubble() const override;
   void UpdateImpl() override;
-  SkColor GetForegroundColor() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
  protected:
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc
index 0a950fe7..448f827b 100644
--- a/chrome/browser/ui/views/sad_tab_view.cc
+++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -577,9 +577,8 @@
   layout->StartRowWithPadding(views::GridLayout::kFixedSize, column_set_id,
                               views::GridLayout::kFixedSize,
                               unrelated_vertical_spacing_large);
-  help_link_ =
-      layout->AddView(std::move(help_link), 1.0, 1.0,
-                      views::GridLayout::LEADING, views::GridLayout::CENTER);
+  layout->AddView(std::move(help_link), 1.0, 1.0, views::GridLayout::LEADING,
+                  views::GridLayout::CENTER);
   action_button_ =
       layout->AddView(std::move(action_button), 1.0, 1.0,
                       views::GridLayout::TRAILING, views::GridLayout::LEADING);
@@ -614,6 +613,27 @@
   AttachToWebView();
 }
 
+void SadTabView::LinkClicked(views::Link* source, int event_flags) {
+  PerformAction(Action::HELP_LINK);
+}
+
+void SadTabView::ButtonPressed(views::Button* sender, const ui::Event& event) {
+  DCHECK_EQ(action_button_, sender);
+  PerformAction(Action::BUTTON);
+}
+
+void SadTabView::OnPaint(gfx::Canvas* canvas) {
+  if (!painted_) {
+    RecordFirstPaint();
+    painted_ = true;
+  }
+  View::OnPaint(canvas);
+}
+
+void SadTabView::RemovedFromWidget() {
+  owner_ = nullptr;
+}
+
 void SadTabView::AttachToWebView() {
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
   // This can be null during prefetch.
@@ -646,28 +666,6 @@
   title_->SizeToFit(max_width);
 }
 
-void SadTabView::LinkClicked(views::Link* source, int event_flags) {
-  PerformAction(Action::HELP_LINK);
-}
-
-void SadTabView::ButtonPressed(views::Button* sender,
-                               const ui::Event& event) {
-  DCHECK_EQ(action_button_, sender);
-  PerformAction(Action::BUTTON);
-}
-
-void SadTabView::OnPaint(gfx::Canvas* canvas) {
-  if (!painted_) {
-    RecordFirstPaint();
-    painted_ = true;
-  }
-  View::OnPaint(canvas);
-}
-
-void SadTabView::RemovedFromWidget() {
-  owner_ = nullptr;
-}
-
 SadTab* SadTab::Create(content::WebContents* web_contents,
                        SadTabKind kind) {
   return new SadTabView(web_contents, kind);
diff --git a/chrome/browser/ui/views/sad_tab_view.h b/chrome/browser/ui/views/sad_tab_view.h
index 0ff2ffa..cc5697be 100644
--- a/chrome/browser/ui/views/sad_tab_view.h
+++ b/chrome/browser/ui/views/sad_tab_view.h
@@ -8,8 +8,6 @@
 #include "chrome/browser/ui/sad_tab.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/link_listener.h"
-#include "ui/views/controls/styled_label.h"
-#include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/view.h"
 
 namespace content {
@@ -71,7 +69,6 @@
   bool painted_ = false;
   views::Label* message_;
   std::vector<views::Label*> bullet_labels_;
-  views::Link* help_link_;
   views::LabelButton* action_button_;
   views::Label* title_;
   views::WebView* owner_ = nullptr;
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 cd92b27..e6064bcf9 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
@@ -89,11 +89,6 @@
   return "SendTabToSelfIconView";
 }
 
-SkColor SendTabToSelfIconView::GetForegroundColor() const {
-  return GetOmniboxColor(GetThemeProvider(),
-                         OmniboxPart::LOCATION_BAR_TEXT_DEFAULT);
-}
-
 base::string16 SendTabToSelfIconView::GetTextForTooltipAndAccessibleName()
     const {
   return l10n_util::GetStringUTF16(IDS_OMNIBOX_TOOLTIP_SEND_TAB_TO_SELF);
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 8d6c5cd..fd17837 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
@@ -27,7 +27,6 @@
   // PageActionIconView:
   views::BubbleDialogDelegateView* GetBubble() const override;
   void UpdateImpl() override;
-  SkColor GetForegroundColor() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
   // gfx::AnimationDelegate:
diff --git a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
index f783104..d7c02dbd 100644
--- a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
+++ b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
@@ -28,24 +28,8 @@
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/widget/widget.h"
 
-namespace {
-
-// Minimum width for the multi-line label.
-const int kMinimumDialogLabelWidth = 400;
-
-std::unique_ptr<views::Link> CreateExtraView(views::LinkListener* listener) {
-  auto advanced_link = std::make_unique<views::Link>(
-      l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_ADVANCED));
-
-  advanced_link->set_listener(listener);
-  advanced_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  return advanced_link;
-}
-
-}  // namespace
-
 // static
-OneClickSigninDialogView* OneClickSigninDialogView::dialog_view_ = NULL;
+OneClickSigninDialogView* OneClickSigninDialogView::dialog_view_ = nullptr;
 
 // static
 void OneClickSigninDialogView::ShowDialog(
@@ -80,16 +64,19 @@
     base::OnceCallback<void(bool)> confirmed_callback)
     : delegate_(std::move(delegate)),
       email_(email),
-      confirmed_callback_(std::move(confirmed_callback)),
-      advanced_link_(nullptr),
-      learn_more_link_(nullptr) {
+      confirmed_callback_(std::move(confirmed_callback)) {
   DialogDelegate::set_button_label(
       ui::DIALOG_BUTTON_OK,
       l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_OK_BUTTON));
   DialogDelegate::set_button_label(
       ui::DIALOG_BUTTON_CANCEL,
       l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_UNDO_BUTTON));
-  advanced_link_ = DialogDelegate::SetExtraView(::CreateExtraView(this));
+
+  auto advanced_link = std::make_unique<views::Link>(
+      l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_ADVANCED));
+  advanced_link->set_listener(this);
+  advanced_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  advanced_link_ = DialogDelegate::SetExtraView(std::move(advanced_link));
 
   DCHECK(!confirmed_callback_.is_null());
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
@@ -117,6 +104,8 @@
       IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE_NEW, email_));
   label->SetMultiLine(true);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  // Minimum width for the multi-line label.
+  constexpr int kMinimumDialogLabelWidth = 400;
   label->SizeToFit(kMinimumDialogLabelWidth);
   layout->AddView(std::move(label));
 
@@ -144,17 +133,15 @@
   // we'll be destroyed asynchronously and the shown state will be checked
   // before then.
   DCHECK_EQ(dialog_view_, this);
-  dialog_view_ = NULL;
+  dialog_view_ = nullptr;
 }
 
 void OneClickSigninDialogView::LinkClicked(views::Link* source,
                                            int event_flags) {
-  if (source == learn_more_link_) {
+  if (source == learn_more_link_)
     delegate_->OnLearnMoreLinkClicked(true);
-  } else if (source == advanced_link_) {
-    std::move(confirmed_callback_).Run(true);
-    GetWidget()->Close();
-  }
+  else if ((source == advanced_link_) && Accept())
+    Hide();
 }
 
 bool OneClickSigninDialogView::Accept() {
diff --git a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.h b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.h
index 6b9b26a..bb2d6bd 100644
--- a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.h
+++ b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.h
@@ -75,10 +75,10 @@
   base::OnceCallback<void(bool)> confirmed_callback_;
 
   // Link to sync setup advanced page.
-  views::Link* advanced_link_;
+  views::Link* advanced_link_ = nullptr;
 
   // Link to the Learn More details page
-  views::Link* learn_more_link_;
+  views::Link* learn_more_link_ = nullptr;
 
   // The bubble, if we're showing one.
   static OneClickSigninDialogView* dialog_view_;
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
index d6a2343..d7379407 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/window/dialog_delegate.h"
 
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
index 5e2ac3a..859896fc 100644
--- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
+++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
@@ -28,9 +28,6 @@
   return new TabModalConfirmDialogViews(std::move(delegate), web_contents);
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// TabModalConfirmDialogViews, constructor & destructor:
-
 TabModalConfirmDialogViews::TabModalConfirmDialogViews(
     std::unique_ptr<TabModalConfirmDialogDelegate> delegate,
     content::WebContents* web_contents)
@@ -74,17 +71,11 @@
   GetWidget()->Close();
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// TabModalConfirmDialogViews, views::LinkListener implementation:
-
 void TabModalConfirmDialogViews::LinkClicked(views::Link* source,
                                              int event_flags) {
   delegate_->LinkClicked(ui::DispositionFromEventFlags(event_flags));
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// TabModalConfirmDialogViews, views::DialogDelegate implementation:
-
 int TabModalConfirmDialogViews::GetDialogButtons() const {
   return delegate_->GetDialogButtons();
 }
@@ -127,9 +118,6 @@
   return nullptr;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// TabModalConfirmDialogViews, views::WidgetDelegate implementation:
-
 views::View* TabModalConfirmDialogViews::GetContentsView() {
   return message_box_view_;
 }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 33b39e8..0eb1b70 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -321,11 +321,12 @@
 }
 
 void BrowserTabStripController::UngroupAllTabsInGroup(
-    tab_groups::TabGroupId group) {
+    const tab_groups::TabGroupId& group) {
   model_->RemoveFromGroup(ListTabsInGroup(group));
 }
 
-void BrowserTabStripController::AddNewTabInGroup(tab_groups::TabGroupId group) {
+void BrowserTabStripController::AddNewTabInGroup(
+    const tab_groups::TabGroupId& group) {
   const std::vector<int> tabs = ListTabsInGroup(group);
   model_->delegate()->AddTabAt(GURL(), tabs.back() + 1, true, group);
 }
@@ -438,23 +439,23 @@
 }
 
 base::string16 BrowserTabStripController::GetGroupTitle(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   return model_->group_model()->GetTabGroup(group)->visual_data()->title();
 }
 
 tab_groups::TabGroupColorId BrowserTabStripController::GetGroupColorId(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   return model_->group_model()->GetTabGroup(group)->visual_data()->color();
 }
 
 void BrowserTabStripController::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& visual_data) {
   model_->group_model()->GetTabGroup(group)->SetVisualData(visual_data);
 }
 
 std::vector<int> BrowserTabStripController::ListTabsInGroup(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   return model_->group_model()->GetTabGroup(group)->ListTabs();
 }
 
@@ -613,7 +614,7 @@
 void BrowserTabStripController::TabGroupedStateChanged(
     base::Optional<tab_groups::TabGroupId> group,
     int index) {
-  tabstrip_->AddTabToGroup(group, index);
+  tabstrip_->AddTabToGroup(std::move(group), index);
 }
 
 void BrowserTabStripController::SetTabNeedsAttentionAt(int index,
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index 00d5839dc..67c4b15 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -64,8 +64,8 @@
   void AddSelectionFromAnchorTo(int model_index) override;
   bool BeforeCloseTab(int model_index, CloseTabSource source) override;
   void CloseTab(int model_index, CloseTabSource source) override;
-  void UngroupAllTabsInGroup(tab_groups::TabGroupId group) override;
-  void AddNewTabInGroup(tab_groups::TabGroupId group) override;
+  void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) override;
+  void AddNewTabInGroup(const tab_groups::TabGroupId& group) override;
   void MoveTab(int start_index, int final_index) override;
   void ShowContextMenuForTab(Tab* tab,
                              const gfx::Point& p,
@@ -78,14 +78,15 @@
   void OnStartedDragging() override;
   void OnStoppedDragging() override;
   void OnKeyboardFocusedTabChanged(base::Optional<int> index) override;
-  base::string16 GetGroupTitle(tab_groups::TabGroupId group_id) const override;
+  base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group_id) const override;
   tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group_id) const override;
+      const tab_groups::TabGroupId& group_id) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
   std::vector<int> ListTabsInGroup(
-      tab_groups::TabGroupId group_id) const override;
+      const tab_groups::TabGroupId& group_id) const override;
   bool IsFrameCondensed() const override;
   bool HasVisibleBackgroundTabShapes() const override;
   bool EverHasVisibleBackgroundTabShapes() const override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
index 2081095..e8227b4 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -92,29 +92,29 @@
   }
 }
 base::string16 FakeBaseTabStripController::GetGroupTitle(
-    tab_groups::TabGroupId group_id) const {
+    const tab_groups::TabGroupId& group_id) const {
   return fake_group_data_.title();
 }
 
 tab_groups::TabGroupColorId FakeBaseTabStripController::GetGroupColorId(
-    tab_groups::TabGroupId group_id) const {
+    const tab_groups::TabGroupId& group_id) const {
   return fake_group_data_.color();
 }
 
 void FakeBaseTabStripController::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& visual_data) {
   fake_group_data_ = visual_data;
 }
 
 void FakeBaseTabStripController::UngroupAllTabsInGroup(
-    tab_groups::TabGroupId group) {}
+    const tab_groups::TabGroupId& group) {}
 
 void FakeBaseTabStripController::AddNewTabInGroup(
-    tab_groups::TabGroupId group) {}
+    const tab_groups::TabGroupId& group) {}
 
 std::vector<int> FakeBaseTabStripController::ListTabsInGroup(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   std::vector<int> result;
   for (size_t i = 0; i < tab_groups_.size(); i++) {
     if (tab_groups_[i] == group)
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
index dd27ce66..e1ab6d30 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -58,15 +58,17 @@
   void OnStartedDragging() override;
   void OnStoppedDragging() override;
   void OnKeyboardFocusedTabChanged(base::Optional<int> index) override;
-  base::string16 GetGroupTitle(tab_groups::TabGroupId group_id) const override;
+  base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group_id) const override;
   tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group_id) const override;
+      const tab_groups::TabGroupId& group_id) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
-  std::vector<int> ListTabsInGroup(tab_groups::TabGroupId group) const override;
-  void UngroupAllTabsInGroup(tab_groups::TabGroupId group) override;
-  void AddNewTabInGroup(tab_groups::TabGroupId group) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
+  std::vector<int> ListTabsInGroup(
+      const tab_groups::TabGroupId& group) const override;
+  void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) override;
+  void AddNewTabInGroup(const tab_groups::TabGroupId& group) override;
   bool IsFrameCondensed() const override;
   bool HasVisibleBackgroundTabShapes() const override;
   bool EverHasVisibleBackgroundTabShapes() const override;
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h
index 927a476..0d5ef06 100644
--- a/chrome/browser/ui/views/tabs/tab_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -7,7 +7,6 @@
 
 #include "chrome/browser/ui/tabs/tab_types.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
-#include "components/tab_groups/tab_group_color.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
 
@@ -22,6 +21,7 @@
 class Rect;
 }
 namespace tab_groups {
+enum class TabGroupColorId;
 class TabGroupId;
 class TabGroupVisualData;
 }  // namespace tab_groups
@@ -190,27 +190,28 @@
   virtual float GetHoverOpacityForRadialHighlight() const = 0;
 
   // Returns the displayed title of the given |group|.
-  virtual base::string16 GetGroupTitle(tab_groups::TabGroupId group) const = 0;
+  virtual base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group) const = 0;
 
   // Returns the color ID of the given |group|.
   virtual tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group) const = 0;
+      const tab_groups::TabGroupId& group) const = 0;
 
   // Returns the actual painted color of the given |group|, which depends on the
   // current theme.
   virtual SkColor GetPaintedGroupColor(
-      tab_groups::TabGroupColorId color_id) const = 0;
+      const tab_groups::TabGroupColorId& color_id) const = 0;
 
   // Sets the title and color ID of the given |group|.
   virtual void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) = 0;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) = 0;
 
-  virtual void CloseAllTabsInGroup(tab_groups::TabGroupId group) = 0;
+  virtual void CloseAllTabsInGroup(const tab_groups::TabGroupId& group) = 0;
 
-  virtual void UngroupAllTabsInGroup(tab_groups::TabGroupId group) = 0;
+  virtual void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) = 0;
 
-  virtual void AddNewTabInGroup(tab_groups::TabGroupId group) = 0;
+  virtual void AddNewTabInGroup(const tab_groups::TabGroupId& group) = 0;
 
   virtual const Browser* GetBrowser() = 0;
 
diff --git a/chrome/browser/ui/views/tabs/tab_drag_context.h b/chrome/browser/ui/views/tabs/tab_drag_context.h
index 2ada47d..68a0b63 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_context.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_context.h
@@ -36,7 +36,7 @@
   virtual bool IsTabPinned(const Tab* tab) const = 0;
   virtual int GetPinnedTabCount() const = 0;
   virtual TabGroupHeader* GetTabGroupHeader(
-      tab_groups::TabGroupId group) const = 0;
+      const tab_groups::TabGroupId& group) const = 0;
   virtual TabStripModel* GetTabStripModel() = 0;
 
   // Returns the index of the active tab in touch mode, or no value if not in
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
index 501ed6ca..c52f8727 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -47,9 +47,10 @@
 }  // namespace
 
 // static
-views::Widget* TabGroupEditorBubbleView::Show(TabGroupHeader* anchor_view,
-                                              TabController* tab_controller,
-                                              tab_groups::TabGroupId group) {
+views::Widget* TabGroupEditorBubbleView::Show(
+    TabGroupHeader* anchor_view,
+    TabController* tab_controller,
+    const tab_groups::TabGroupId& group) {
   views::Widget* const widget = BubbleDialogDelegateView::CreateBubble(
       new TabGroupEditorBubbleView(anchor_view, tab_controller, group));
   widget->Show();
@@ -73,7 +74,7 @@
 TabGroupEditorBubbleView::TabGroupEditorBubbleView(
     TabGroupHeader* anchor_view,
     TabController* tab_controller,
-    tab_groups::TabGroupId group)
+    const tab_groups::TabGroupId& group)
     : tab_controller_(tab_controller),
       group_(group),
       title_field_controller_(this),
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
index 539de70..3bcbf802 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
@@ -7,9 +7,6 @@
 
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/views/tabs/tab_group_header.h"
-#include "components/tab_groups/tab_group_color.h"
-#include "components/tab_groups/tab_group_id.h"
-#include "components/tab_groups/tab_group_visual_data.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/textfield/textfield.h"
@@ -21,7 +18,13 @@
 class Size;
 }
 
+namespace tab_groups {
+enum class TabGroupColorId;
+class TabGroupId;
+}  // namespace tab_groups
+
 class ColorPickerView;
+class TabGroupHeader;
 
 // A dialog for changing a tab group's visual parameters.
 class TabGroupEditorBubbleView : public views::BubbleDialogDelegateView {
@@ -30,7 +33,7 @@
   // bubble's widget.
   static views::Widget* Show(TabGroupHeader* anchor_view,
                              TabController* tab_controller,
-                             tab_groups::TabGroupId group);
+                             const tab_groups::TabGroupId& group);
 
   // views::BubbleDialogDelegateView:
   gfx::Size CalculatePreferredSize() const override;
@@ -40,7 +43,7 @@
  private:
   TabGroupEditorBubbleView(TabGroupHeader* anchor_view,
                            TabController* tab_controller,
-                           tab_groups::TabGroupId group);
+                           const tab_groups::TabGroupId& group);
   ~TabGroupEditorBubbleView() override;
 
   void UpdateGroup();
diff --git a/chrome/browser/ui/views/tabs/tab_group_header.cc b/chrome/browser/ui/views/tabs/tab_group_header.cc
index b111c1f..4ab7bdc1 100644
--- a/chrome/browser/ui/views/tabs/tab_group_header.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_header.cc
@@ -37,7 +37,7 @@
 #include "ui/views/view_class_properties.h"
 
 TabGroupHeader::TabGroupHeader(TabStrip* tab_strip,
-                               tab_groups::TabGroupId group)
+                               const tab_groups::TabGroupId& group)
     : tab_strip_(tab_strip) {
   DCHECK(tab_strip);
 
diff --git a/chrome/browser/ui/views/tabs/tab_group_header.h b/chrome/browser/ui/views/tabs/tab_group_header.h
index 6be00fb..b0318808 100644
--- a/chrome/browser/ui/views/tabs/tab_group_header.h
+++ b/chrome/browser/ui/views/tabs/tab_group_header.h
@@ -22,7 +22,7 @@
 // strip flow and positioned left of the leftmost tab in the group.
 class TabGroupHeader : public TabSlotView {
  public:
-  TabGroupHeader(TabStrip* tab_strip, tab_groups::TabGroupId group);
+  TabGroupHeader(TabStrip* tab_strip, const tab_groups::TabGroupId& group);
   ~TabGroupHeader() override = default;
 
   // TabSlotView:
diff --git a/chrome/browser/ui/views/tabs/tab_group_highlight.cc b/chrome/browser/ui/views/tabs/tab_group_highlight.cc
index bea4397e..2dd97c2 100644
--- a/chrome/browser/ui/views/tabs/tab_group_highlight.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_highlight.cc
@@ -13,7 +13,7 @@
 #include "ui/views/view.h"
 
 TabGroupHighlight::TabGroupHighlight(TabGroupViews* tab_group_views,
-                                     tab_groups::TabGroupId group)
+                                     const tab_groups::TabGroupId& group)
     : tab_group_views_(tab_group_views), group_(group) {
   // Set non-zero bounds to start with, so that painting isn't pruned.
   // Needed because UpdateBounds() happens during OnPaint(), which is called
diff --git a/chrome/browser/ui/views/tabs/tab_group_highlight.h b/chrome/browser/ui/views/tabs/tab_group_highlight.h
index cbf0d818..58be510 100644
--- a/chrome/browser/ui/views/tabs/tab_group_highlight.h
+++ b/chrome/browser/ui/views/tabs/tab_group_highlight.h
@@ -16,9 +16,9 @@
 class TabGroupHighlight : public views::View {
  public:
   TabGroupHighlight(TabGroupViews* tab_group_views,
-                    tab_groups::TabGroupId group);
+                    const tab_groups::TabGroupId& group);
 
-  tab_groups::TabGroupId group() const { return group_; }
+  const tab_groups::TabGroupId& group() const { return group_; }
 
   // views::View:
   void OnPaint(gfx::Canvas* canvas) override;
diff --git a/chrome/browser/ui/views/tabs/tab_group_underline.cc b/chrome/browser/ui/views/tabs/tab_group_underline.cc
index 033fc0e0..455cd25 100644
--- a/chrome/browser/ui/views/tabs/tab_group_underline.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_underline.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_group_header.h"
 #include "chrome/browser/ui/views/tabs/tab_group_views.h"
+#include "components/tab_groups/tab_group_id.h"
 #include "components/tab_groups/tab_group_visual_data.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/canvas.h"
@@ -21,7 +22,7 @@
 constexpr int TabGroupUnderline::kStrokeThickness;
 
 TabGroupUnderline::TabGroupUnderline(TabGroupViews* tab_group_views,
-                                     tab_groups::TabGroupId group)
+                                     const tab_groups::TabGroupId& group)
     : tab_group_views_(tab_group_views), group_(group) {
   // Set non-zero bounds to start with, so that painting isn't pruned.
   // Needed because UpdateBounds() happens during OnPaint(), which is called
diff --git a/chrome/browser/ui/views/tabs/tab_group_underline.h b/chrome/browser/ui/views/tabs/tab_group_underline.h
index f07816b..af61bb6 100644
--- a/chrome/browser/ui/views/tabs/tab_group_underline.h
+++ b/chrome/browser/ui/views/tabs/tab_group_underline.h
@@ -19,9 +19,9 @@
   static int GetStrokeInset();
 
   TabGroupUnderline(TabGroupViews* tab_group_views,
-                    tab_groups::TabGroupId group);
+                    const tab_groups::TabGroupId& group);
 
-  tab_groups::TabGroupId group() const { return group_; }
+  const tab_groups::TabGroupId& group() const { return group_; }
 
   // Updates the bounds of the underline for painting.
   void UpdateBounds();
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.cc b/chrome/browser/ui/views/tabs/tab_group_views.cc
index 446c05e..c88bbc18 100644
--- a/chrome/browser/ui/views/tabs/tab_group_views.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_views.cc
@@ -16,10 +16,12 @@
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
 #include "components/tab_groups/tab_group_color.h"
+#include "components/tab_groups/tab_group_id.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
-TabGroupViews::TabGroupViews(TabStrip* tab_strip, tab_groups::TabGroupId group)
+TabGroupViews::TabGroupViews(TabStrip* tab_strip,
+                             const tab_groups::TabGroupId& group)
     : tab_strip_(tab_strip), group_(group) {
   header_ = std::make_unique<TabGroupHeader>(tab_strip_, group_);
   header_->set_owned_by_client();
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.h b/chrome/browser/ui/views/tabs/tab_group_views.h
index d361d991..2d4aa93 100644
--- a/chrome/browser/ui/views/tabs/tab_group_views.h
+++ b/chrome/browser/ui/views/tabs/tab_group_views.h
@@ -21,7 +21,7 @@
 // calculations and updates. Painting is done in TabStrip.
 class TabGroupViews {
  public:
-  TabGroupViews(TabStrip* tab_strip, tab_groups::TabGroupId group);
+  TabGroupViews(TabStrip* tab_strip, const tab_groups::TabGroupId& group);
   ~TabGroupViews();
 
   tab_groups::TabGroupId group() const { return group_; }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index f3a0e32..58d02869 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -437,7 +437,7 @@
   }
 
   TabGroupHeader* GetTabGroupHeader(
-      tab_groups::TabGroupId group) const override {
+      const tab_groups::TabGroupId& group) const override {
     return tab_strip_->group_header(group);
   }
 
@@ -548,7 +548,7 @@
         }
       }
     } else {
-      index = GetInsertionIndexFrom(dragged_bounds, 0, group);
+      index = GetInsertionIndexFrom(dragged_bounds, 0, std::move(group));
     }
     if (!index) {
       const int last_tab_right = ideal_bounds(GetTabCount() - 1).right();
@@ -807,7 +807,7 @@
       return last_tab + 1;
 
     return GetInsertionIndexWithGroup(dragged_bounds, insertion_index.value(),
-                                      group);
+                                      std::move(group));
   }
 
   // Like GetInsertionIndexFrom(), but searches backwards from |start| to the
@@ -1243,10 +1243,10 @@
 
 void TabStrip::AddTabToGroup(base::Optional<tab_groups::TabGroupId> group,
                              int model_index) {
-  tab_at(model_index)->set_group(group);
+  tab_at(model_index)->set_group(std::move(group));
 }
 
-void TabStrip::OnGroupCreated(tab_groups::TabGroupId group) {
+void TabStrip::OnGroupCreated(const tab_groups::TabGroupId& group) {
   std::unique_ptr<TabGroupViews> group_view =
       std::make_unique<TabGroupViews>(this, group);
   AddChildView(group_view->header());
@@ -1259,7 +1259,7 @@
   group_views_[group] = std::move(group_view);
 }
 
-void TabStrip::OnGroupContentsChanged(tab_groups::TabGroupId group) {
+void TabStrip::OnGroupContentsChanged(const tab_groups::TabGroupId& group) {
   DCHECK(group_views_[group]);
   // The group header may be in the wrong place if the tab didn't actually
   // move in terms of model indices.
@@ -1269,7 +1269,7 @@
   AnimateToIdealBounds();
 }
 
-void TabStrip::OnGroupVisualsChanged(tab_groups::TabGroupId group) {
+void TabStrip::OnGroupVisualsChanged(const tab_groups::TabGroupId& group) {
   DCHECK(group_views_[group]);
   group_views_[group]->UpdateVisuals();
   // The group title may have changed size, so update bounds.
@@ -1277,7 +1277,7 @@
   AnimateToIdealBounds();
 }
 
-void TabStrip::OnGroupClosed(tab_groups::TabGroupId group) {
+void TabStrip::OnGroupClosed(const tab_groups::TabGroupId& group) {
   bounds_animator_.StopAnimatingView(group_header(group));
   layout_helper_->RemoveGroupHeader(group);
   UpdateIdealBounds();
@@ -1920,17 +1920,18 @@
   return radial_highlight_opacity_;
 }
 
-base::string16 TabStrip::GetGroupTitle(tab_groups::TabGroupId group) const {
+base::string16 TabStrip::GetGroupTitle(
+    const tab_groups::TabGroupId& group) const {
   return controller_->GetGroupTitle(group);
 }
 
 tab_groups::TabGroupColorId TabStrip::GetGroupColorId(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   return controller_->GetGroupColorId(group);
 }
 
 SkColor TabStrip::GetPaintedGroupColor(
-    tab_groups::TabGroupColorId color_id) const {
+    const tab_groups::TabGroupColorId& color_id) const {
   const tab_groups::TabGroupColor color_data =
       tab_groups::GetTabGroupColorSet().at(color_id);
 
@@ -1942,12 +1943,12 @@
 }
 
 void TabStrip::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& visual_data) {
   controller_->SetVisualDataForGroup(group, visual_data);
 }
 
-void TabStrip::CloseAllTabsInGroup(tab_groups::TabGroupId group) {
+void TabStrip::CloseAllTabsInGroup(const tab_groups::TabGroupId& group) {
   UpdateHoverCard(nullptr);
 
   std::vector<int> tabs = controller_->ListTabsInGroup(group);
@@ -1956,12 +1957,12 @@
   }
 }
 
-void TabStrip::UngroupAllTabsInGroup(tab_groups::TabGroupId group) {
+void TabStrip::UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) {
   UpdateHoverCard(nullptr);
   controller_->UngroupAllTabsInGroup(group);
 }
 
-void TabStrip::AddNewTabInGroup(tab_groups::TabGroupId group) {
+void TabStrip::AddNewTabInGroup(const tab_groups::TabGroupId& group) {
   controller_->AddNewTabInGroup(group);
 }
 
@@ -2677,7 +2678,8 @@
   }
 }
 
-void TabStrip::OnGroupCloseAnimationCompleted(tab_groups::TabGroupId group) {
+void TabStrip::OnGroupCloseAnimationCompleted(
+    const tab_groups::TabGroupId& group) {
   group_views_.erase(group);
   // TODO(crbug.com/905491): We might want to simulate a mouse move here, like
   // we do in OnTabCloseAnimationCompleted.
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 106bb02..5f10c21 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -172,21 +172,21 @@
                      int model_index);
 
   // Creates the views associated with a newly-created tab group.
-  void OnGroupCreated(tab_groups::TabGroupId group);
+  void OnGroupCreated(const tab_groups::TabGroupId& group);
 
   // Updates the group's contents and metadata when its tab membership changes.
   // This should be called when a tab is added to or removed from a group.
-  void OnGroupContentsChanged(tab_groups::TabGroupId group);
+  void OnGroupContentsChanged(const tab_groups::TabGroupId& group);
 
   // Updates the group's tabs and header when its associated TabGroupVisualData
   // changes. This should be called when the result of
   // |TabStripController::GetGroupTitle(group)| or
   // |TabStripController::GetGroupColorId(group)| changes.
-  void OnGroupVisualsChanged(tab_groups::TabGroupId group);
+  void OnGroupVisualsChanged(const tab_groups::TabGroupId& group);
 
   // Destroys the views associated with a recently deleted tab group. The
   // associated view mappings are erased in OnGroupCloseAnimationCompleted().
-  void OnGroupClosed(tab_groups::TabGroupId group);
+  void OnGroupClosed(const tab_groups::TabGroupId& group);
 
   // Returns true if the tab is not partly or fully clipped (due to overflow),
   // and the tab couldn't become partly clipped due to changing the selected tab
@@ -215,7 +215,7 @@
   Tab* tab_at(int index) const { return tabs_.view_at(index); }
 
   // Returns the TabGroupHeader with ID |id|.
-  TabGroupHeader* group_header(tab_groups::TabGroupId id) {
+  TabGroupHeader* group_header(const tab_groups::TabGroupId& id) {
     return group_views_[id].get()->header();
   }
 
@@ -305,17 +305,18 @@
   gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override;
   float GetHoverOpacityForTab(float range_parameter) const override;
   float GetHoverOpacityForRadialHighlight() const override;
-  base::string16 GetGroupTitle(tab_groups::TabGroupId group) const override;
+  base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group) const override;
   tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group) const override;
+      const tab_groups::TabGroupId& group) const override;
   SkColor GetPaintedGroupColor(
-      tab_groups::TabGroupColorId color_id) const override;
+      const tab_groups::TabGroupColorId& color_id) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
-  void CloseAllTabsInGroup(tab_groups::TabGroupId group) override;
-  void UngroupAllTabsInGroup(tab_groups::TabGroupId group) override;
-  void AddNewTabInGroup(tab_groups::TabGroupId group) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
+  void CloseAllTabsInGroup(const tab_groups::TabGroupId& group) override;
+  void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) override;
+  void AddNewTabInGroup(const tab_groups::TabGroupId& group) override;
   const Browser* GetBrowser() override;
 
   // MouseWatcherListener:
@@ -499,7 +500,7 @@
 
   // Cleans up the TabGroupHeader for |group| from the TabStrip. This is called
   // from the tab animation code and is not a general-purpose method.
-  void OnGroupCloseAnimationCompleted(tab_groups::TabGroupId group);
+  void OnGroupCloseAnimationCompleted(const tab_groups::TabGroupId& group);
 
   // Invoked from StoppedDraggingTabs to cleanup |view|. If |view| is known
   // |is_first_view| is set to true.
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h
index 1fbca576..c0bc7f41 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -11,7 +11,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
-#include "components/tab_groups/tab_group_color.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
 
@@ -23,6 +22,7 @@
 }
 
 namespace tab_groups {
+enum class TabGroupColorId;
 class TabGroupId;
 class TabGroupVisualData;
 }  // namespace tab_groups
@@ -83,10 +83,10 @@
   virtual void CloseTab(int index, CloseTabSource source) = 0;
 
   // Ungroups the tabs at the specified index in the model.
-  virtual void UngroupAllTabsInGroup(tab_groups::TabGroupId group) = 0;
+  virtual void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) = 0;
 
   // Adds a new tab to end of the tab group.
-  virtual void AddNewTabInGroup(tab_groups::TabGroupId group) = 0;
+  virtual void AddNewTabInGroup(const tab_groups::TabGroupId& group) = 0;
 
   // Moves the tab at |start_index| so that it is now at |final_index|, sliding
   // any tabs in between left or right as appropriate.
@@ -130,20 +130,21 @@
   virtual void OnKeyboardFocusedTabChanged(base::Optional<int> index) = 0;
 
   // Returns the displayed title of the given |group|.
-  virtual base::string16 GetGroupTitle(tab_groups::TabGroupId group) const = 0;
+  virtual base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group) const = 0;
 
   // Returns the color ID of the given |group|.
   virtual tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group) const = 0;
+      const tab_groups::TabGroupId& group) const = 0;
 
   // Sets the title and color ID of the given |group|.
   virtual void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) = 0;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) = 0;
 
   // Returns the list of tabs in the given |group|.
   virtual std::vector<int> ListTabsInGroup(
-      tab_groups::TabGroupId group) const = 0;
+      const tab_groups::TabGroupId& group) const = 0;
 
   // Determines whether the top frame is condensed vertically, as when the
   // window is maximized. If true, the top frame is just the height of a tab,
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index 0b0009f7..3bef479 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -120,29 +120,30 @@
   }
   float GetHoverOpacityForRadialHighlight() const override { return 1.0f; }
 
-  base::string16 GetGroupTitle(tab_groups::TabGroupId group_id) const override {
+  base::string16 GetGroupTitle(
+      const tab_groups::TabGroupId& group_id) const override {
     return base::string16();
   }
 
   tab_groups::TabGroupColorId GetGroupColorId(
-      tab_groups::TabGroupId group_id) const override {
+      const tab_groups::TabGroupId& group_id) const override {
     return tab_groups::TabGroupColorId();
   }
 
   SkColor GetPaintedGroupColor(
-      tab_groups::TabGroupColorId color_id) const override {
+      const tab_groups::TabGroupColorId& color_id) const override {
     return SkColor();
   }
 
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override {}
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override {}
 
-  void CloseAllTabsInGroup(tab_groups::TabGroupId group) override {}
+  void CloseAllTabsInGroup(const tab_groups::TabGroupId& group) override {}
 
-  void UngroupAllTabsInGroup(tab_groups::TabGroupId group) override {}
+  void UngroupAllTabsInGroup(const tab_groups::TabGroupId& group) override {}
 
-  void AddNewTabInGroup(tab_groups::TabGroupId group) override {}
+  void AddNewTabInGroup(const tab_groups::TabGroupId& group) override {}
 
   const Browser* GetBrowser() override { return nullptr; }
 
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc
index 2e3689be..8a68945 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -1000,12 +1000,9 @@
 
 bool AppMenu::ShouldExecuteCommandWithoutClosingMenu(int command_id,
                                                      const ui::Event& event) {
-  if (IsRecentTabsCommand(command_id) && event.IsMouseEvent()) {
-    const auto disposition = ui::DispositionFromEventFlags(event.flags());
-    if (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)
-      return true;
-  }
-  return false;
+  return IsRecentTabsCommand(command_id) && event.IsMouseEvent() &&
+         (ui::DispositionFromEventFlags(event.flags()) ==
+          WindowOpenDisposition::NEW_BACKGROUND_TAB);
 }
 
 void AppMenu::BookmarkModelChanged() {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.cc
index f8ecf69..c1ada80 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h"
 
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h"
@@ -70,8 +71,7 @@
 SkColor
 ToolbarAccountIconContainerView::GetIconLabelBubbleSurroundingForegroundColor()
     const {
-  return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+  return GetIconColor();
 }
 
 SkColor ToolbarAccountIconContainerView::GetIconLabelBubbleInkDropColor()
@@ -79,6 +79,11 @@
   return GetToolbarInkDropBaseColor(this);
 }
 
+SkColor ToolbarAccountIconContainerView::GetIconLabelBubbleBackgroundColor()
+    const {
+  return GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR);
+}
+
 float ToolbarAccountIconContainerView::GetPageActionInkDropVisibleOpacity()
     const {
   return kToolbarInkDropVisibleOpacity;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h
index fcde9a2..10f7192 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h
@@ -34,6 +34,7 @@
   // IconLabelBubbleView::Delegate:
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override;
   SkColor GetIconLabelBubbleInkDropColor() const override;
+  SkColor GetIconLabelBubbleBackgroundColor() const override;
 
   // PageActionIconView::Delegate:
   float GetPageActionInkDropVisibleOpacity() const override;
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 7d3c8e3..97195506 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -471,10 +471,6 @@
   HandleComboboxPerformAction(static_cast<ComboboxID>(combobox->GetID()));
 }
 
-void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
-  HandleLinkClicked(static_cast<LinkID>(source->GetID()));
-}
-
 void TranslateBubbleView::ShowOptionsMenu(views::Button* source) {
   // Recreate the menu model as translated languages can change while the menu
   // is not showing, which invalidates these text strings.
@@ -733,17 +729,6 @@
   translate::ReportUiAction(translate::DONE_BUTTON_CLICKED);
 }
 
-void TranslateBubbleView::HandleLinkClicked(
-    TranslateBubbleView::LinkID sender_id) {
-  switch (sender_id) {
-    case LINK_ID_ADVANCED: {
-      SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
-      translate::ReportUiAction(translate::ADVANCED_LINK_CLICKED);
-      break;
-    }
-  }
-}
-
 void TranslateBubbleView::HandleComboboxPerformAction(
     TranslateBubbleView::ComboboxID sender_id) {
   switch (sender_id) {
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 48a5a497..36618a9b 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -28,7 +28,6 @@
 #include "ui/views/controls/combobox/combobox_listener.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
@@ -46,7 +45,6 @@
 class TranslateBubbleView : public LocationBarBubbleDelegateView,
                             public views::ButtonListener,
                             public views::ComboboxListener,
-                            public views::LinkListener,
                             public ui::SimpleMenuModel::Delegate,
                             public views::StyledLabelListener,
                             public views::TabbedPaneListener {
@@ -103,9 +101,6 @@
   // views::ComboboxListener:
   void OnPerformAction(views::Combobox* combobox) override;
 
-  // views::LinkListener:
-  void LinkClicked(views::Link* source, int event_flags) override;
-
   // ui::SimpleMenuModel::Delegate:
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
@@ -124,10 +119,6 @@
   void CloseBubble() override;
 
  private:
-  enum LinkID {
-    LINK_ID_ADVANCED,
-  };
-
   enum ButtonID {
     BUTTON_ID_TRANSLATE,
     BUTTON_ID_DONE,
@@ -222,9 +213,6 @@
   // Triggers options menu in TAB UI.
   void ShowOptionsMenuTab(views::Button* source);
 
-  // Handles the event when the user clicks a link.
-  void HandleLinkClicked(LinkID sender_id);
-
   // Handles the event when the user changes an index of a combobox.
   void HandleComboboxPerformAction(ComboboxID sender_id);
 
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
index a3c3e79..98409f9 100644
--- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
@@ -53,7 +53,6 @@
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/events/event.h"
-#include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
@@ -386,16 +385,18 @@
     page_action_icon_container_view_->controller()->UpdateAll();
   }
 
-  void SetIconColor(SkColor icon_color) {
-    icon_color_ = icon_color;
+  void SetColors(SkColor foreground_color, SkColor background_color) {
+    foreground_color_ = foreground_color;
+    background_color_ = background_color;
     if (web_app_origin_text_)
-      web_app_origin_text_->SetTextColor(icon_color);
+      web_app_origin_text_->SetTextColor(foreground_color_);
     if (content_settings_container_)
-      content_settings_container_->SetIconColor(icon_color);
+      content_settings_container_->SetIconColor(foreground_color_);
     if (extensions_container_)
-      extensions_container_->OverrideIconColor(icon_color);
-    page_action_icon_container_view_->controller()->SetIconColor(icon_color);
-    web_app_menu_button_->SetColor(icon_color);
+      extensions_container_->OverrideIconColor(foreground_color_);
+    page_action_icon_container_view_->controller()->SetIconColor(
+        foreground_color_);
+    web_app_menu_button_->SetColor(foreground_color_);
   }
 
   ContentSettingsContainer* content_settings_container() {
@@ -479,11 +480,10 @@
 
   // IconLabelBubbleView::Delegate:
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override {
-    return GetNativeTheme()->GetSystemColor(
-        ui::NativeTheme::kColorId_TextfieldDefaultColor);
+    return foreground_color_;
   }
-  SkColor GetIconLabelBubbleInkDropColor() const override {
-    return icon_color_;
+  SkColor GetIconLabelBubbleBackgroundColor() const override {
+    return background_color_;
   }
 
   // ContentSettingImageView::Delegate:
@@ -530,7 +530,8 @@
   // The containing browser view.
   BrowserView* const browser_view_;
 
-  SkColor icon_color_ = gfx::kPlaceholderColor;
+  SkColor foreground_color_ = gfx::kPlaceholderColor;
+  SkColor background_color_ = gfx::kPlaceholderColor;
 
   // All remaining members are owned by the views hierarchy.
   WebAppOriginText* web_app_origin_text_ = nullptr;
@@ -650,12 +651,8 @@
 }
 
 WebAppFrameToolbarView::WebAppFrameToolbarView(views::Widget* widget,
-                                               BrowserView* browser_view,
-                                               SkColor active_color,
-                                               SkColor inactive_color)
-    : browser_view_(browser_view),
-      active_color_(active_color),
-      inactive_color_(inactive_color) {
+                                               BrowserView* browser_view)
+    : browser_view_(browser_view) {
   DCHECK(browser_view_);
   DCHECK(web_app::AppBrowserController::IsForWebAppBrowser(
       browser_view_->browser()));
@@ -699,7 +696,6 @@
                                     views::MaximumFlexSizeRule::kPreferred)
                                     .WithOrder(1));
 
-  UpdateChildrenColor();
   UpdateStatusIconsVisibility();
 
   DCHECK(!browser_view_->toolbar_button_provider() ||
@@ -720,12 +716,15 @@
 void WebAppFrameToolbarView::UpdateCaptionColors() {
   const BrowserNonClientFrameView* frame_view =
       browser_view_->frame()->GetFrameView();
+  DCHECK(frame_view);
 
-  // frame_view is nullptr during BrowserNonClientFrameViewAsh::Init().
-  if (!frame_view)
-    return;
-  active_color_ = frame_view->GetCaptionColor(BrowserFrameActiveState::kActive);
-  inactive_color_ =
+  active_background_color_ =
+      frame_view->GetFrameColor(BrowserFrameActiveState::kActive);
+  active_foreground_color_ =
+      frame_view->GetCaptionColor(BrowserFrameActiveState::kActive);
+  inactive_background_color_ =
+      frame_view->GetFrameColor(BrowserFrameActiveState::kInactive);
+  inactive_foreground_color_ =
       frame_view->GetCaptionColor(BrowserFrameActiveState::kInactive);
   UpdateChildrenColor();
 }
@@ -868,6 +867,10 @@
   PreferredSizeChanged();
 }
 
+void WebAppFrameToolbarView::OnThemeChanged() {
+  UpdateCaptionColors();
+}
+
 views::View* WebAppFrameToolbarView::GetContentSettingContainerForTesting() {
   return right_container_->content_settings_container();
 }
@@ -879,8 +882,11 @@
 }
 
 void WebAppFrameToolbarView::UpdateChildrenColor() {
-  const SkColor icon_color = paint_as_active_ ? active_color_ : inactive_color_;
+  const SkColor foreground_color =
+      paint_as_active_ ? active_foreground_color_ : inactive_foreground_color_;
   if (left_container_)
-    left_container_->SetIconColor(icon_color);
-  right_container_->SetIconColor(icon_color);
+    left_container_->SetIconColor(foreground_color);
+  right_container_->SetColors(
+      foreground_color,
+      paint_as_active_ ? active_background_color_ : inactive_background_color_);
 }
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.h b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.h
index 7df3f80..447ec0e 100644
--- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.h
+++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.h
@@ -13,6 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/views/accessible_pane_view.h"
 
 namespace views {
@@ -46,16 +47,13 @@
   // The total duration of the origin fade animation.
   static base::TimeDelta OriginTotalDuration();
 
-  // |active_color| and |inactive_color| indicate the colors to use
-  // for button icons when the window is focused and blurred respectively.
-  WebAppFrameToolbarView(views::Widget* widget,
-                         BrowserView* browser_view,
-                         SkColor active_color,
-                         SkColor inactive_color);
+  WebAppFrameToolbarView(views::Widget* widget, BrowserView* browser_view);
   ~WebAppFrameToolbarView() override;
 
   void UpdateStatusIconsVisibility();
 
+  // Called when the caption colors may have changed; updates the local values
+  // and triggers a repaint if necessary.
   void UpdateCaptionColors();
 
   // Sets the container to paints its buttons the active/inactive color.
@@ -68,7 +66,7 @@
                                         int y,
                                         int available_height);
 
-  SkColor active_color_for_testing() const { return active_color_; }
+  SkColor active_color_for_testing() const { return active_foreground_color_; }
 
   // ToolbarButtonProvider:
   BrowserActionsContainer* GetBrowserActionsContainer() override;
@@ -94,6 +92,7 @@
   // views::AccessiblePaneView:
   const char* GetClassName() const override;
   void ChildPreferredSizeChanged(views::View* child) override;
+  void OnThemeChanged() override;
 
  private:
   friend class WebAppNonClientFrameViewAshTest;
@@ -118,8 +117,10 @@
 
   // Button and text colors.
   bool paint_as_active_ = true;
-  SkColor active_color_;
-  SkColor inactive_color_;
+  SkColor active_background_color_ = gfx::kPlaceholderColor;
+  SkColor active_foreground_color_ = gfx::kPlaceholderColor;
+  SkColor inactive_background_color_ = gfx::kPlaceholderColor;
+  SkColor inactive_foreground_color_ = gfx::kPlaceholderColor;
 
   class NavigationButtonContainer;
   class ToolbarButtonContainer;
diff --git a/chrome/browser/ui/webui/history/navigation_handler.cc b/chrome/browser/ui/webui/history/navigation_handler.cc
index d0f0669..036c575 100644
--- a/chrome/browser/ui/webui/history/navigation_handler.cc
+++ b/chrome/browser/ui/webui/history/navigation_handler.cc
@@ -46,11 +46,9 @@
   bool middle_button = (button == 1.0);
 
   WindowOpenDisposition disposition = ui::DispositionFromClick(
-      middle_button, alt_key, ctrl_key, meta_key, shift_key);
-  if (disposition == WindowOpenDisposition::CURRENT_TAB &&
-      target_string == "_blank")
-    disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-
+      middle_button, alt_key, ctrl_key, meta_key, shift_key,
+      (target_string == "_blank") ? WindowOpenDisposition::NEW_FOREGROUND_TAB
+                                  : WindowOpenDisposition::CURRENT_TAB);
   web_ui()->GetWebContents()->OpenURL(
       content::OpenURLParams(GURL(url_string), content::Referrer(), disposition,
                              ui::PAGE_TRANSITION_LINK, false));
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 8d4bd19..d109ef5 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
-#include "chrome/browser/ssl/bad_clock_blocking_page.h"
 #include "chrome/browser/ssl/blocked_interception_blocking_page.h"
 #include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
 #include "chrome/browser/ssl/mitm_software_blocking_page.h"
@@ -26,6 +25,7 @@
 #include "chrome/common/url_constants.h"
 #include "components/grit/components_resources.h"
 #include "components/safe_browsing/db/database_manager.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
 #include "components/security_interstitials/content/origin_policy_ui.h"
 #include "components/security_interstitials/core/ssl_error_options_mask.h"
 #include "components/security_interstitials/core/ssl_error_ui.h"
@@ -233,9 +233,9 @@
   if (strict_enforcement)
     options_mask |=
         security_interstitials::SSLErrorOptionsMask::STRICT_ENFORCEMENT;
-  return new BadClockBlockingPage(web_contents, cert_error, ssl_info,
-                                  request_url, base::Time::Now(), clock_state,
-                                  nullptr);
+  return ChromeSecurityBlockingPageFactory::CreateBadClockBlockingPage(
+      web_contents, cert_error, ssl_info, request_url, base::Time::Now(),
+      clock_state, nullptr);
 }
 
 LookalikeUrlInterstitialPage* CreateLookalikeInterstitialPage(
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
index d0828b0..343a70b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -308,8 +308,7 @@
         new BrowsingDataDatabaseHelper(profile_),
         new BrowsingDataLocalStorageHelper(profile_),
         new BrowsingDataAppCacheHelper(storage_partition->GetAppCacheService()),
-        new BrowsingDataIndexedDBHelper(
-            storage_partition->GetIndexedDBContext()),
+        new BrowsingDataIndexedDBHelper(storage_partition),
         BrowsingDataFileSystemHelper::Create(
             storage_partition->GetFileSystemContext()),
         new BrowsingDataServiceWorkerHelper(
diff --git a/chrome/chrome_cleaner/components/recovery_component.cc b/chrome/chrome_cleaner/components/recovery_component.cc
index a9532321..d6573a4b 100644
--- a/chrome/chrome_cleaner/components/recovery_component.cc
+++ b/chrome/chrome_cleaner/components/recovery_component.cc
@@ -38,7 +38,7 @@
 
 const char kComponentDownloadUrl[] =
     "https://clients2.google.com/service/update2/crx?response=redirect&os=win"
-    "&arch=x86&installsource=swreporter&x=id%3Dnpdjjkjlcidkjlamlmmdelcjbcpdjocm"
+    "&installsource=swreporter&x=id%3Dnpdjjkjlcidkjlamlmmdelcjbcpdjocm"
     "%26v%3D0.0.0.0%26uc&acceptformat=crx3";
 
 // CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm.
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index a5886b12..0af7474 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -30,7 +30,10 @@
   "accessibilityPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
-    "whitelist": [ "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E" ]
+    "whitelist": [
+      "0D209B5E4401BB8E7873B5AB5B1346A1CB067015",  // http://crbug.com/1039158
+      "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E"
+    ]
   },
   "activeTab": {
     "channel": "stable",
diff --git a/chrome/common/heap_profiler_controller.cc b/chrome/common/heap_profiler_controller.cc
index bfa3b11..14d4c8c 100644
--- a/chrome/common/heap_profiler_controller.cc
+++ b/chrome/common/heap_profiler_controller.cc
@@ -107,7 +107,10 @@
         static_cast<size_t>(
             std::llround(static_cast<double>(sample.total) / sample.size)),
         1);
-    profile_builder.OnSampleCompleted(std::move(frames), sample.total, count);
+    // Heap "samples" represent allocation stacks aggregated over time so do not
+    // have a meaningful timestamp.
+    profile_builder.OnSampleCompleted(std::move(frames), base::TimeTicks(),
+                                      sample.total, count);
   }
 
   profile_builder.OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
diff --git a/chrome/common/prerender.mojom b/chrome/common/prerender.mojom
index a85ea0ad..26760c55 100644
--- a/chrome/common/prerender.mojom
+++ b/chrome/common/prerender.mojom
@@ -12,9 +12,6 @@
 
   // Cancels prerendering because of an unsupported scheme.
   CancelPrerenderForUnsupportedScheme(url.mojom.Url url);
-
-  // Cancels prerendering because of a synchronous deferred redirect.
-  CancelPrerenderForSyncDeferredRedirect();
 };
 
 // PrerenderDispatcher Messages
diff --git a/chrome/common/prerender_url_loader_throttle.cc b/chrome/common/prerender_url_loader_throttle.cc
index df102b8..b885082 100644
--- a/chrome/common/prerender_url_loader_throttle.cc
+++ b/chrome/common/prerender_url_loader_throttle.cc
@@ -35,13 +35,6 @@
     canceler->CancelPrerenderForUnsupportedScheme(url);
 }
 
-void CancelPrerenderForSyncDeferredRedirect(
-    PrerenderURLLoaderThrottle::CancelerGetterCallback callback) {
-  chrome::mojom::PrerenderCanceler* canceler = std::move(callback).Run();
-  if (canceler)
-    canceler->CancelPrerenderForSyncDeferredRedirect();
-}
-
 // Returns true if the response has a "no-store" cache control header.
 bool IsNoStoreResponse(const network::mojom::URLResponseHead& response_head) {
   return response_head.headers &&
@@ -74,8 +67,9 @@
 }
 
 void PrerenderURLLoaderThrottle::DetachFromCurrentSequence() {
-  // This method is only called for synchronous XHR from the main thread.
-  sync_xhr_ = true;
+  // This method is only called for synchronous XHR from the main thread which
+  // should not occur during a NoStatePrerender.
+  NOTREACHED();
 }
 
 void PrerenderURLLoaderThrottle::WillStartRequest(
@@ -180,18 +174,8 @@
              resource_type_ != content::ResourceType::kMainFrame) {
     // Only defer redirects with the Follow-Only-When-Prerender-Shown
     // header. Do not defer redirects on main frame loads.
-    if (sync_xhr_) {
-      // Cancel on deferred synchronous requests. Those will
-      // indefinitely hang up a renderer process.
-      canceler_getter_task_runner_->PostTask(
-          FROM_HERE, base::BindOnce(CancelPrerenderForSyncDeferredRedirect,
-                                    std::move(canceler_getter_)));
-      delegate_->CancelWithError(net::ERR_ABORTED);
-    } else {
-      // Defer the redirect until the prerender is used or canceled.
-      *defer = true;
-      deferred_ = true;
-    }
+    *defer = true;
+    deferred_ = true;
   }
 }
 
diff --git a/chrome/common/prerender_url_loader_throttle.h b/chrome/common/prerender_url_loader_throttle.h
index 13dd4e1..b3879d8 100644
--- a/chrome/common/prerender_url_loader_throttle.h
+++ b/chrome/common/prerender_url_loader_throttle.h
@@ -61,7 +61,6 @@
   std::string histogram_prefix_;
 
   bool deferred_ = false;
-  bool sync_xhr_ = false;
   int redirect_count_ = 0;
   content::ResourceType resource_type_;
 
diff --git a/chrome/credential_provider/DEPS b/chrome/credential_provider/DEPS
index 0cbd04b..2ad44f9 100644
--- a/chrome/credential_provider/DEPS
+++ b/chrome/credential_provider/DEPS
@@ -5,6 +5,7 @@
   "+components/crash",
   "+google_apis",
   "+third_party/boringssl/src/include",
+  "+third_party/re2",
 ]
 
 specific_include_rules = {
diff --git a/chrome/credential_provider/gaiacp/BUILD.gn b/chrome/credential_provider/gaiacp/BUILD.gn
index d71a93b..89f0947b 100644
--- a/chrome/credential_provider/gaiacp/BUILD.gn
+++ b/chrome/credential_provider/gaiacp/BUILD.gn
@@ -120,6 +120,7 @@
     "//components/crash/content/app:crash_export_thunks",
     "//components/crash/content/app:run_as_crashpad_handler",
     "//third_party/boringssl",
+    "//third_party/re2",
   ]
   if (is_component_build) {
     deps += [ "//content/public/common" ]
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 8596c1e..1c06c52 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -60,6 +60,7 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/escape.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/re2/src/re2/re2.h"
 
 namespace credential_provider {
 
@@ -72,7 +73,7 @@
     "grant_type=refresh_token&"
     "refresh_token=%s&"
     "scope=%s";
-constexpr wchar_t kRegEnableADAssociation[] = L"enable_ad_association";
+constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
 // The access scopes should be separated by single space.
 constexpr char kAccessScopes[] =
     "https://www.googleapis.com/auth/admin.directory.user";
@@ -82,7 +83,8 @@
 // users directory api.
 constexpr char kKeyCustomSchemas[] = "customSchemas";
 constexpr char kKeyEmployeeData[] = "employeeData";
-constexpr char kKeyAdUpn[] = "ad_upn";
+constexpr char kKeySamAccountName[] = "samAccountName";
+constexpr char kKeyLocalAccountInfo[] = "localAccountInfo";
 
 base::string16 GetEmailDomains() {
   std::vector<wchar_t> email_domains(16);
@@ -122,14 +124,18 @@
 }
 
 // Use WinHttpUrlFetcher to communicate with the admin sdk and fetch the active
-// directory UPN from the admin configured custom attributes.
-HRESULT GetAdUpnFromCloudDirectory(const base::string16& email,
-                                   const std::string& access_token,
-                                   std::string* ad_upn,
-                                   BSTR* error_text) {
+// directory samAccountName if available and list of local account name mapping
+// configured as custom attributes.
+HRESULT GetExistingAccountMappingFromCD(
+    const base::string16& email,
+    const std::string& access_token,
+    std::string* sam_account_name,
+    std::vector<std::string>* local_account_names,
+    BSTR* error_text) {
   DCHECK(email.size() > 0);
   DCHECK(access_token.size() > 0);
-  DCHECK(ad_upn);
+  DCHECK(sam_account_name);
+  DCHECK(local_account_names);
   DCHECK(error_text);
   *error_text = nullptr;
 
@@ -158,10 +164,20 @@
     return hr;
   }
 
-  *ad_upn = SearchForKeyInStringDictUTF8(
+  *sam_account_name = SearchForKeyInStringDictUTF8(
       cd_user_response_json_string,
-      {kKeyCustomSchemas, kKeyEmployeeData, kKeyAdUpn});
-  return S_OK;
+      {kKeyCustomSchemas, kKeyEmployeeData, kKeySamAccountName});
+
+  hr = SearchForListInStringDictUTF8(
+      "value", cd_user_response_json_string,
+      {kKeyCustomSchemas, kKeyEmployeeData, kKeyLocalAccountInfo},
+      local_account_names);
+
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "Attempt to parse localAccountInfo failed.";
+  }
+
+  return hr;
 }
 
 // Request a downscoped access token using the refresh token provided in the
@@ -216,29 +232,148 @@
   return S_OK;
 }
 
-// Find an AD account associated with GCPW user if one exists.
+HRESULT GetUserAndDomainInfo(
+    const std::string& sam_account_name,
+    const std::vector<std::string>& local_account_names,
+    base::string16* existing_sid,
+    BSTR* error_text) {
+  base::string16 user_name;
+  base::string16 domain_name;
+
+  bool is_ad_user =
+      OSUserManager::Get()->IsDeviceDomainJoined() && !sam_account_name.empty();
+  // Login via existing AD account mapping when the device is domain joined if
+  // the AD account mapping is available.
+  if (is_ad_user) {
+    // The format for ad_upn custom attribute is domainName/userName.
+    const base::char16 kSlashDelimiter[] = STRING16_LITERAL("/");
+    std::vector<base::string16> tokens =
+        base::SplitString(base::UTF8ToUTF16(sam_account_name), kSlashDelimiter,
+                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+    // Values fetched from custom attribute shouldn't be empty.
+    if (tokens.size() != 2) {
+      LOGFN(ERROR) << "Found unparseable samAccountName in cloud directory : "
+                   << sam_account_name;
+      *error_text =
+          CGaiaCredentialBase::AllocErrorString(IDS_INVALID_AD_UPN_BASE);
+      return E_FAIL;
+    }
+
+    domain_name = tokens.at(0);
+    user_name = tokens.at(1);
+  } else {
+    // Fallback to using local account mapping for all other scenarios.
+
+    // Step 1: Filter out invalid local account names based on serial number
+    // etc. The mapping would look like "un:abcd,sn:1234" where "un" represents
+    // the local user name and "sn" represents the serial number of the device.
+    // Note that "sn" is optional, but it is recommended to be used by the IT
+    // admin.
+
+    // The variable that holds all the local accounts which has
+    // a matching serial number of the device.
+    std::vector<base::string16> filtered_local_account_names;
+
+    // The variable that holds all the local accounts which doesn't have
+    // any serial_number mapping in custom attributes.
+    std::vector<base::string16> filtered_local_account_names_no_sn;
+
+    for (auto local_account_name : local_account_names) {
+      // The format for local_account_name custom attribute is
+      // "un:abcd,sn:1234" where "un:abcd" would always exist and "sn:1234" is
+      // optional.
+      std::string username;
+      std::string serial_number;
+      // Note: "?:" is used to signify non-capturing groups. For more details,
+      // look at https://github.com/google/re2/wiki/Syntax link.
+      re2::RE2::FullMatch(local_account_name, "un:([^,]+)(?:,sn:(\\w+))?",
+                          &username, &serial_number);
+
+      if (!username.empty() && !serial_number.empty()) {
+        std::string device_serial_number =
+            base::UTF16ToUTF8(GetSerialNumber().c_str());
+        if (base::EqualsCaseInsensitiveASCII(serial_number,
+                                             device_serial_number))
+          filtered_local_account_names.push_back(base::UTF8ToUTF16(username));
+      } else if (!username.empty()) {
+        filtered_local_account_names_no_sn.push_back(
+            base::UTF8ToUTF16(username));
+      }
+    }
+
+    // Step 2: If more than one mapping found on both the above lists
+    // OR no mapping found on either one of them, then return NTE_NOT_FOUND.
+    if (filtered_local_account_names.size() != 1 &&
+        filtered_local_account_names_no_sn.size() != 1) {
+      return NTE_NOT_FOUND;
+    }
+
+    // Step 3: Assign the extracted user name to user_name variable so that we
+    // can verify for existence of SID on the device with the extracted user
+    // name on the current windows device.
+    user_name = filtered_local_account_names.size() == 1
+                    ? filtered_local_account_names.at(0)
+                    : filtered_local_account_names_no_sn.at(0);
+    domain_name = OSUserManager::GetLocalDomain();
+  }
+
+  OSUserManager* os_user_manager = OSUserManager::Get();
+  DCHECK(os_user_manager);
+  LOGFN(INFO) << "Get user sid for user " << user_name << " and domain name "
+              << domain_name;
+  HRESULT hr = os_user_manager->GetUserSID(domain_name.c_str(),
+                                           user_name.c_str(), existing_sid);
+
+  if (existing_sid->length() > 0) {
+    LOGFN(INFO) << "Found existing SID = " << *existing_sid;
+    return S_OK;
+  }
+
+  LOGFN(ERROR) << "No existing sid found with user name : " << user_name
+               << " and domain name: " << domain_name << ". hr=" << putHR(hr);
+
+  if (is_ad_user) {
+    *error_text =
+        CGaiaCredentialBase::AllocErrorString(IDS_INVALID_AD_UPN_BASE);
+    LOGFN(ERROR) << "Could not find a valid samAccountName.";
+  }
+
+  // For non-AD usecase, we will fallback to creating new local account
+  // instead of failing the login attempt.
+  return NTE_NOT_FOUND;
+}
+
+// Find an existing account associated with GCPW user if one exists.
 // (1) Verifies if the gaia user has a corresponding mapping in Google
 //   Admin SDK Users Directory and contains the custom_schema that contains
-//   the ad_upn or local_user_name for the corresponding user.
+//   the sam_account_name or local_user_info for the corresponding user.
 // (2) If there is an entry in cloud directory, gcpw would search for the SID
 //   corresponding to that user entry on the device.
 // (3) If a SID is found, then it would log the user onto the device using
 //   username extracted from Google Admin SDK Users Directory and password
 //   being the same as the gaia entity.
 // (4) If there is no entry found in cloud directory, gcpw would fallback to
-//   attempting creation of a new user on the device.
+//   create a new local user on the device.
+//
+// Below are the scenarios where we fallback to create a new local user:
+// (1) No mapping available in user's cloud directory custom schema attributes.
+// (2) If a local user mapping exists but the extracted domainname/username
+//     combination doesn't have a valid SID.
 //
 // Below are the failure scenarios :
-// (1) If an invalid upn is set in the custom attributes, the login would fail.
-// (2) If an attempt to find SID from domain controller failed, then we fail
-//     the login.
-// Note that if an empty upn is found in the custom attribute, then the login
-// would try and attempt to create local user.
-HRESULT FindAdUserSidIfAvailable(const std::string& refresh_token,
-                                 const base::string16& email,
-                                 wchar_t* sid,
-                                 const DWORD sid_length,
-                                 BSTR* error_text) {
+// (1) Failed getting a downscoped access token from refresh token.
+// (2) If communication with cloud directory fails, then we fail the login.
+// (3) If an attempt to find SID from domain controller or local machine failed,
+//     then we fail the login.
+// (4) Parsing the samAccountName or localAccountInfo failed.
+// (5) If an AD user mapping exists but the extracted domainname/username
+//     combination doesn't have a valid SID.
+HRESULT FindExistingUserSidIfAvailable(const std::string& refresh_token,
+                                       const base::string16& email,
+                                       wchar_t* sid,
+                                       const DWORD sid_length,
+                                       BSTR* error_text) {
   DCHECK(sid);
   DCHECK(error_text);
   *error_text = nullptr;
@@ -254,59 +389,24 @@
   }
 
   // Step 2: Make a get call to admin sdk using the fetched access_token and
-  // retrieve the ad_upn.
-  std::string ad_upn;
-  hr = GetAdUpnFromCloudDirectory(email, access_token, &ad_upn, error_text);
+  // retrieve the sam_account_name.
+  std::string sam_account_name;
+  std::vector<std::string> local_account_names;
+  hr = GetExistingAccountMappingFromCD(email, access_token, &sam_account_name,
+                                       &local_account_names, error_text);
   if (FAILED(hr)) {
-    LOGFN(ERROR) << "GetAdUpnFromCloudDirectory hr=" << putHR(hr);
+    LOGFN(ERROR) << "GetExistingAccountMappingFromCD hr=" << putHR(hr);
     return hr;
   }
 
-  base::string16 ad_domain;
-  base::string16 ad_user;
-  if (ad_upn.empty()) {
-    LOGFN(INFO) << "Found empty ad_upn in cloud directory. Fall back to "
-                   "creating local account";
-    return S_FALSE;
-  }
-
-  // The format for ad_upn custom attribute is domainName/userName.
-  const base::char16 kSlashDelimiter[] = STRING16_LITERAL("/");
-  std::vector<base::string16> tokens =
-      base::SplitString(base::UTF8ToUTF16(ad_upn), kSlashDelimiter,
-                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
-  // Values fetched from custom attribute shouldn't be empty.
-  if (tokens.size() != 2) {
-    LOGFN(ERROR) << "Found unparseable ad_upn in cloud directory : " << ad_upn;
-    *error_text =
-        CGaiaCredentialBase::AllocErrorString(IDS_INVALID_AD_UPN_BASE);
-    return E_FAIL;
-  }
-
-  ad_domain = tokens.at(0);
-  ad_user = tokens.at(1);
-
-  OSUserManager* os_user_manager = OSUserManager::Get();
-  DCHECK(os_user_manager);
   base::string16 existing_sid = base::string16();
+  hr = GetUserAndDomainInfo(sam_account_name, local_account_names,
+                            &existing_sid, error_text);
 
-  LOGFN(INFO) << "Get user sid for user " << ad_user << " and domain name "
-              << ad_domain;
-  hr = os_user_manager->GetUserSID(ad_domain.c_str(), ad_user.c_str(),
-                                   &existing_sid);
-  LOGFN(INFO) << "GetUserSID result=" << hr;
-
-  if (existing_sid.length() > 0) {
-    LOGFN(INFO) << "Found existing SID = " << existing_sid;
+  if (SUCCEEDED(hr))
     wcscpy_s(sid, sid_length, existing_sid.c_str());
-    return S_OK;
-  } else {
-    LOGFN(ERROR) << "No existing sid found with UPN : " << ad_upn;
-    *error_text =
-        CGaiaCredentialBase::AllocErrorString(IDS_INVALID_AD_UPN_BASE);
-    return E_FAIL;
-  }
+
+  return hr;
 }
 
 // Tries to find a user associated to the gaia_id stored in |result| under the
@@ -359,29 +459,36 @@
     LOGFN(INFO) << "Found existing SID created in GCPW registry entry = "
                 << sid;
     has_existing_user_sid = true;
-  } else if (CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() &&
-             OSUserManager::Get()->IsDeviceDomainJoined()) {
-    LOGFN(INFO) << "No existing SID found in the GCPW registry.";
+  } else if (CGaiaCredentialBase::IsCloudAssociationEnabled()) {
+    LOGFN(INFO) << "Lookup cloud association.";
 
     std::string refresh_token = GetDictStringUTF8(result, kKeyRefreshToken);
-    hr = FindAdUserSidIfAvailable(refresh_token, email, sid, sid_length,
-                                  error_text);
-    if (FAILED(hr)) {
-      LOGFN(ERROR) << "Failed finding AD user sid for GCPW user. hr="
+    hr = FindExistingUserSidIfAvailable(refresh_token, email, sid, sid_length,
+                                        error_text);
+
+    has_existing_user_sid = true;
+    if (hr == NTE_NOT_FOUND) {
+      LOGFN(ERROR) << "No valid sid mapping found."
+                   << "Fallback to create a new local user account. hr="
+                   << putHR(hr);
+      has_existing_user_sid = false;
+    } else if (FAILED(hr)) {
+      LOGFN(ERROR) << "Failed finding existing user sid for GCPW user. hr="
                    << putHR(hr);
       return hr;
-    } else if (hr == S_OK) {
-      has_existing_user_sid = true;
     }
+
   } else {
-    LOGFN(INFO) << "Falling back to creation of new user";
+    LOGFN(INFO) << "Fallback to create a new local user account";
   }
 
   if (has_existing_user_sid) {
     HRESULT hr = OSUserManager::Get()->FindUserBySID(
         sid, username, username_length, domain, domain_length);
-    if (SUCCEEDED(hr))
-      return hr;
+    if (FAILED(hr))
+      *error_text =
+          CGaiaCredentialBase::AllocErrorString(IDS_INTERNAL_ERROR_BASE);
+    return hr;
   }
 
   LOGFN(INFO) << "No existing user found associated to gaia id:" << *gaia_id;
@@ -653,9 +760,9 @@
 CGaiaCredentialBase::UIProcessInfo::~UIProcessInfo() {}
 
 // static
-bool CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() {
-  DWORD enable_ad_association = 0;
-  return GetGlobalFlagOrDefault(kRegEnableADAssociation, enable_ad_association);
+bool CGaiaCredentialBase::IsCloudAssociationEnabled() {
+  DWORD enable_cloud_association = 0;
+  return GetGlobalFlagOrDefault(kRegCloudAssociation, enable_cloud_association);
 }
 
 // static
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.h b/chrome/credential_provider/gaiacp/gaia_credential_base.h
index 025d1f5..7976bf8 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.h
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.h
@@ -75,8 +75,8 @@
     StdParentHandles parent_handles;
   };
 
-  // Returns true if "enable_ad_association" registry key is set to 1.
-  static bool IsAdToGoogleAssociationEnabled();
+  // Returns true if "enable_cloud_association" registry key is set to 1.
+  static bool IsCloudAssociationEnabled();
 
  protected:
   CGaiaCredentialBase();
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
index 3592cd9..5e0fa3c 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -1145,8 +1145,11 @@
   EXPECT_EQ(test->GetFinalEmail(), email);
 }
 
-// Test various active directory sign in scenarios.
-class GcpGaiaCredentialBaseAdScenariosTest : public GcpGaiaCredentialBaseTest {
+// Test various existing local account mapping or active directory account
+// mapping in cloud sign-in scenarios.
+class GcpGaiaCredentialBaseCloudMappingTest
+    : public GcpGaiaCredentialBaseTest,
+      public ::testing::WithParamInterface<bool> {
  protected:
   void SetUp() override;
 
@@ -1158,25 +1161,27 @@
       "%s?projection=full&viewType=domain_public",
       net::EscapeUrlEncodedData(kDefaultEmail, true).c_str());
   GaiaUrls* gaia_urls_ = GaiaUrls::GetInstance();
+  bool is_ad_user = GetParam();
 };
 
-void GcpGaiaCredentialBaseAdScenariosTest::SetUp() {
+void GcpGaiaCredentialBaseCloudMappingTest::SetUp() {
   GcpGaiaCredentialBaseTest::SetUp();
+  if (is_ad_user) {
+    // Set the device as a domain joined machine.
+    fake_os_user_manager()->SetIsDeviceDomainJoined(true);
+  }
 
-  // Set the device as a domain joined machine.
-  fake_os_user_manager()->SetIsDeviceDomainJoined(true);
-
-  // Override registry to enable AD association with google.
-  constexpr wchar_t kRegEnableADAssociation[] = L"enable_ad_association";
-  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegEnableADAssociation, 1));
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation, 1));
 
   ASSERT_EQ(S_OK, InitializeProviderAndGetCredential(0, &cred_));
 }
 
 // Fetching downscoped access token required for calling admin sdk failed.
 // The login attempt would fail in this scenario.
-TEST_F(GcpGaiaCredentialBaseAdScenariosTest,
-       GetSerialization_WithAD_CallToFetchDownscopedAccessTokenFailed) {
+TEST_P(GcpGaiaCredentialBaseCloudMappingTest,
+       GetSerialization_CallToFetchDownscopedAccessTokenFailed) {
   // Attempt to fetch the token from gaia fails.
   fake_http_url_fetcher_factory()->SetFakeFailedResponse(
       GURL(gaia_urls_->oauth2_token_url().spec().c_str()), E_FAIL);
@@ -1208,8 +1213,8 @@
 }
 
 // Empty access token returned.
-TEST_F(GcpGaiaCredentialBaseAdScenariosTest,
-       GetSerialization_WithAD_EmptyAccessTokenReturned) {
+TEST_P(GcpGaiaCredentialBaseCloudMappingTest,
+       GetSerialization_EmptyAccessTokenReturned) {
   // Set token result to not contain any access token.
   fake_http_url_fetcher_factory()->SetFakeResponse(
       GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
@@ -1239,9 +1244,9 @@
                       IDS_EMPTY_ACCESS_TOKEN_BASE));
 }
 
-// Empty AD UPN entry is returned via admin sdk.
-TEST_F(GcpGaiaCredentialBaseAdScenariosTest,
-       GetSerialization_WithAD_NoAdUpnFoundFromAdminSdk) {
+// Empty samAccountName or localAccountInfo is returned via admin sdk.
+TEST_P(GcpGaiaCredentialBaseCloudMappingTest,
+       GetSerialization_NoUserNameFoundFromAdminSdk) {
   // Set token result a valid access token.
   fake_http_url_fetcher_factory()->SetFakeResponse(
       GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
@@ -1269,9 +1274,9 @@
   EXPECT_EQ(2ul, fake_os_user_manager()->GetUserCount());
 }
 
-// Call to the admin sdk to fetch the AD UPN failed.
-TEST_F(GcpGaiaCredentialBaseAdScenariosTest,
-       GetSerialization_WithAD_CallToAdminSdkFailed) {
+// Call to the admin sdk to fetch samAccountName or localAccountInfo failed.
+TEST_P(GcpGaiaCredentialBaseCloudMappingTest,
+       GetSerialization_CallToAdminSdkFailed) {
   // Set token result a valid access token.
   fake_http_url_fetcher_factory()->SetFakeResponse(
       GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
@@ -1305,19 +1310,51 @@
                       IDS_INTERNAL_ERROR_BASE));
 }
 
-// Customer configured invalid ad upn.
+INSTANTIATE_TEST_SUITE_P(All,
+                         GcpGaiaCredentialBaseCloudMappingTest,
+                         ::testing::Values(true, false));
+
+// Test various active directory specific sign in scenarios.
+class GcpGaiaCredentialBaseAdScenariosTest : public GcpGaiaCredentialBaseTest {
+ protected:
+  void SetUp() override;
+
+  // Create provider and start logon.
+  Microsoft::WRL::ComPtr<ICredentialProviderCredential> cred_;
+  // The admin sdk users directory get URL.
+  std::string get_cd_user_url_ = base::StringPrintf(
+      "https://www.googleapis.com/admin/directory/v1/users/"
+      "%s?projection=full&viewType=domain_public",
+      net::EscapeUrlEncodedData(kDefaultEmail, true).c_str());
+  GaiaUrls* gaia_urls_ = GaiaUrls::GetInstance();
+};
+
+void GcpGaiaCredentialBaseAdScenariosTest::SetUp() {
+  GcpGaiaCredentialBaseTest::SetUp();
+
+  // Set the device as a domain joined machine.
+  fake_os_user_manager()->SetIsDeviceDomainJoined(true);
+
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation, 1));
+
+  ASSERT_EQ(S_OK, InitializeProviderAndGetCredential(0, &cred_));
+}
+
+// Customer configured invalid samAccountName.
 TEST_F(GcpGaiaCredentialBaseAdScenariosTest,
        GetSerialization_WithAD_InvalidADUPNConfigured) {
   // Add the user as a domain joined user.
   const wchar_t user_name[] = L"ad_user";
-  const wchar_t domain_name[] = L"ad_domain";
   const wchar_t password[] = L"password";
 
-  CComBSTR ad_sid;
+  const wchar_t domain_name[] = L"ad_domain";
+  CComBSTR existing_user_sid;
   DWORD error;
   HRESULT add_domain_user_hr = fake_os_user_manager()->AddUser(
-      user_name, password, L"fullname", L"comment", true, domain_name, &ad_sid,
-      &error);
+      user_name, password, L"fullname", L"comment", true, domain_name,
+      &existing_user_sid, &error);
   ASSERT_EQ(S_OK, add_domain_user_hr);
   ASSERT_EQ(0u, error);
 
@@ -1328,7 +1365,7 @@
 
   // Invalid configuration in admin sdk. Don't set the username.
   std::string admin_sdk_response = base::StringPrintf(
-      "{\"customSchemas\": {\"employeeData\": {\"ad_upn\":"
+      "{\"customSchemas\": {\"employeeData\": {\"samAccountName\":"
       " \"%ls/\"}}}",
       domain_name);
   fake_http_url_fetcher_factory()->SetFakeResponse(
@@ -1383,7 +1420,7 @@
 
   // Set valid response from admin sdk.
   std::string admin_sdk_response = base::StringPrintf(
-      "{\"customSchemas\": {\"employeeData\": {\"ad_upn\":"
+      "{\"customSchemas\": {\"employeeData\": {\"samAccountName\":"
       " \"%ls/%ls\"}}}",
       domain_name, user_name);
   fake_http_url_fetcher_factory()->SetFakeResponse(
@@ -1426,6 +1463,473 @@
   ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
 }
 
+// Test various existing local account mapping specific in cloud sign in
+// scenarios.
+class GcpGaiaCredentialBaseCloudLocalAccountTest
+    : public GcpGaiaCredentialBaseTest {
+ protected:
+  void SetUp() override;
+
+  // Create provider and start logon.
+  Microsoft::WRL::ComPtr<ICredentialProviderCredential> cred_;
+  // The admin sdk users directory get URL.
+  std::string get_cd_user_url_ = base::StringPrintf(
+      "https://www.googleapis.com/admin/directory/v1/users/"
+      "%s?projection=full&viewType=domain_public",
+      net::EscapeUrlEncodedData(kDefaultEmail, true).c_str());
+  GaiaUrls* gaia_urls_ = GaiaUrls::GetInstance();
+};
+
+void GcpGaiaCredentialBaseCloudLocalAccountTest::SetUp() {
+  GcpGaiaCredentialBaseTest::SetUp();
+
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation, 1));
+
+  ASSERT_EQ(S_OK, InitializeProviderAndGetCredential(0, &cred_));
+}
+
+// Customer configured invalid local account info.
+TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
+       GetSerialization_InvalidLocalAccountInfoConfigured) {
+  // Add the user as a local user.
+  const wchar_t user_name[] = L"local_user";
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  // Invalid configuration in admin sdk. Don't set the username.
+  std::string admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      " \"un:abcd\"}}}");
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  // Make sure new user was created since no valid mapping was found.
+  PSID sid = nullptr;
+  fake_os_user_manager()->GetUserSID(OSUserManager::GetLocalDomain().c_str(),
+                                     kDefaultUsername, &sid);
+  ASSERT_NE(nullptr, sid);
+
+  // New user is created.
+  EXPECT_EQ(3ul, fake_os_user_manager()->GetUserCount());
+
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+}
+
+TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, MultipleLocalAccountInfo) {
+  // Add the user as a local user.
+  const wchar_t user_name[] = L"local_user";
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  std::string admin_sdk_response;
+  // Set a fake serial number.
+  base::string16 serial_number = L"1234";
+  GoogleRegistrationDataForTesting g_registration_data(serial_number);
+
+  const wchar_t another_user_name[] = L"another_local_user";
+
+  // Set valid response from admin sdk with localAccountInfo containing
+  // one mapping with "serial_number" in it and another one without
+  // serial number.
+  admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      "[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls\"}]}}}",
+      user_name, serial_number.c_str(), another_user_name);
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
+
+  // Make sure no user was created and the login happens on the
+  // existing user instead.
+  PSID sid = nullptr;
+  EXPECT_EQ(
+      HRESULT_FROM_WIN32(NERR_UserNotFound),
+      fake_os_user_manager()->GetUserSID(
+          OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
+  ASSERT_EQ(nullptr, sid);
+
+  // Finishing logon process should trigger credential changed and trigger
+  // GetSerialization.
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+
+  // Verify that the registry entry for the user was created.
+  std::wstring sid_str(local_sid, SysStringLen(local_sid));
+
+  wchar_t gaia_id[256];
+  ULONG length = base::size(gaia_id);
+  HRESULT gaia_id_hr =
+      GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
+  ASSERT_EQ(S_OK, gaia_id_hr);
+  ASSERT_TRUE(gaia_id[0]);
+
+  // Verify that the authentication results dictionary is now empty.
+  ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
+}
+
+TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
+       InvalidUserToSerialNumberMapping) {
+  // Add the user as a local user.
+  const wchar_t user_name[] = L"local_user";
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  std::string admin_sdk_response;
+  // Set a fake serial number.
+  base::string16 serial_number = L"1234";
+  GoogleRegistrationDataForTesting g_registration_data(serial_number);
+
+  const wchar_t another_user_name1[] = L"another_local_user_1";
+  const wchar_t another_user_name2[] = L"another_local_user_2";
+
+  // Set valid response from admin sdk with localAccountInfo containing
+  // multiple mappings with matching "serial_number" in it and another
+  // one without serial number.
+  admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      "[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\" },{ "
+      " \"value\": \"un:%ls\" }]}}}",
+      another_user_name1, serial_number.c_str(), another_user_name2,
+      serial_number.c_str(), user_name);
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
+
+  // Make sure no user was created and the login happens on the
+  // existing user instead.
+  PSID sid = nullptr;
+  EXPECT_EQ(
+      HRESULT_FROM_WIN32(NERR_UserNotFound),
+      fake_os_user_manager()->GetUserSID(
+          OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
+  ASSERT_EQ(nullptr, sid);
+
+  // Finishing logon process should trigger credential changed and trigger
+  // GetSerialization.
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+
+  // Verify that the registry entry for the user was created.
+  std::wstring sid_str(local_sid, SysStringLen(local_sid));
+
+  wchar_t gaia_id[256];
+  ULONG length = base::size(gaia_id);
+  HRESULT gaia_id_hr =
+      GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
+  ASSERT_EQ(S_OK, gaia_id_hr);
+  ASSERT_TRUE(gaia_id[0]);
+
+  // Verify that the authentication results dictionary is now empty.
+  ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
+}
+
+TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
+       MultipleValidLocalAccountInfoMapping) {
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  std::string admin_sdk_response;
+  // Set a fake serial number.
+  base::string16 serial_number = L"1234";
+  GoogleRegistrationDataForTesting g_registration_data(serial_number);
+
+  const wchar_t another_user_name1[] = L"another_local_user_1";
+  const wchar_t another_user_name2[] = L"another_local_user_2";
+
+  // Set valid response from admin sdk with localAccountInfo containing
+  // multiple mappings with matching "serial_number" in it and multiple
+  // mappings without serial number.
+  admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      "[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\" },{ "
+      " \"value\": \"un:%ls\" },{ \"value\": \"un:%ls\"}]}}}",
+      another_user_name1, serial_number.c_str(), another_user_name2,
+      serial_number.c_str(), another_user_name1, another_user_name2);
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  // Make sure new user was created since no valid mapping was found.
+  PSID sid = nullptr;
+  fake_os_user_manager()->GetUserSID(OSUserManager::GetLocalDomain().c_str(),
+                                     kDefaultUsername, &sid);
+  ASSERT_NE(nullptr, sid);
+
+  // New user is created.
+  EXPECT_EQ(2ul, fake_os_user_manager()->GetUserCount());
+
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+}
+
+// This is the success scenario where all preconditions are met in the
+// existing cloud local account login scenario. The user is successfully
+// logged in.
+class GaiaCredentialBaseCloudLocalAccountSuccessTest
+    : public GcpGaiaCredentialBaseCloudLocalAccountTest,
+      public ::testing::WithParamInterface<bool> {};
+
+TEST_P(GaiaCredentialBaseCloudLocalAccountSuccessTest, SerialNumber) {
+  bool set_serial_number = GetParam();
+
+  // Add the user as a local user.
+  const wchar_t user_name[] = L"local_user";
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  std::string admin_sdk_response;
+  // Set a fake serial number.
+  base::string16 serial_number = L"1234";
+  GoogleRegistrationDataForTesting g_registration_data(serial_number);
+
+  if (set_serial_number) {
+    // Set valid response from admin sdk.
+    admin_sdk_response = base::StringPrintf(
+        "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+        "[{ \"value\": \"un:%ls,sn:%ls\"}]}}}",
+        user_name, serial_number.c_str());
+  } else {
+    // Set valid response from admin sdk.
+    admin_sdk_response = base::StringPrintf(
+        "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+        "[{ \"value\": \"un:%ls\"}]}}}",
+        user_name);
+  }
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
+
+  // Make sure no user was created and the login happens on the
+  // existing user instead.
+  PSID sid = nullptr;
+  EXPECT_EQ(
+      HRESULT_FROM_WIN32(NERR_UserNotFound),
+      fake_os_user_manager()->GetUserSID(
+          OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
+  ASSERT_EQ(nullptr, sid);
+
+  // Finishing logon process should trigger credential changed and trigger
+  // GetSerialization.
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+
+  // Verify that the registry entry for the user was created.
+  std::wstring sid_str(local_sid, SysStringLen(local_sid));
+
+  wchar_t gaia_id[256];
+  ULONG length = base::size(gaia_id);
+  HRESULT gaia_id_hr =
+      GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
+  ASSERT_EQ(S_OK, gaia_id_hr);
+  ASSERT_TRUE(gaia_id[0]);
+
+  // Verify that the authentication results dictionary is now empty.
+  ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         GaiaCredentialBaseCloudLocalAccountSuccessTest,
+                         ::testing::Values(true, false));
+
+// Existing cloud local account login scenario that was configured incorrectly.
+class GaiaCredentialBaseCDUsernameSuccessTest
+    : public GcpGaiaCredentialBaseCloudLocalAccountTest,
+      public ::testing::WithParamInterface<const wchar_t*> {};
+
+TEST_P(GaiaCredentialBaseCDUsernameSuccessTest, AnyUsername) {
+  const wchar_t* user_name = GetParam();
+
+  // Add the user as a local user.
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  // Set valid response from admin sdk.
+  std::string admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      "[{ \"value\": \"un:%ls\"}]}}}",
+      user_name);
+
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  // New user is not created.
+  EXPECT_EQ(2ul, fake_os_user_manager()->GetUserCount());
+
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+
+  // Verify that the registry entry for the user was created.
+  std::wstring sid_str(local_sid, SysStringLen(local_sid));
+
+  wchar_t gaia_id[256];
+  ULONG length = base::size(gaia_id);
+  HRESULT gaia_id_hr =
+      GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
+  ASSERT_EQ(S_OK, gaia_id_hr);
+  ASSERT_TRUE(gaia_id[0]);
+
+  // Verify that the authentication results dictionary is now empty.
+  ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    GaiaCredentialBaseCDUsernameSuccessTest,
+    ::testing::Values(L"!@#!",        // All non alphanumeric characters
+                      L"user#123",    // Contains non-alphanumeric chars.
+                      L"user123!"));  // Ends with non alphanumeric chars.
+
+// Existing cloud local account login scenario that was configured incorrectly.
+class GaiaCredentialBaseCDSerialNumberFailureTest
+    : public GcpGaiaCredentialBaseCloudLocalAccountTest,
+      public ::testing::WithParamInterface<const wchar_t*> {};
+
+TEST_P(GaiaCredentialBaseCDSerialNumberFailureTest, InvalidSerialNumber) {
+  const wchar_t* serial_number = GetParam();
+
+  // Add the user as a local user.
+  const wchar_t user_name[] = L"local_user";
+  const wchar_t password[] = L"password";
+
+  CComBSTR local_sid;
+  DWORD error;
+  HRESULT hr = fake_os_user_manager()->AddUser(
+      user_name, password, L"fullname", L"comment", true, &local_sid, &error);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(0u, error);
+
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  // Set valid response from admin sdk.
+  std::string admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"employeeData\": {\"localAccountInfo\":"
+      "[{ \"value\": \"un:%ls,sn:%ls\"}]}}}",
+      user_name, serial_number);
+
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred_.As(&test));
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  // Make sure new user was created since no valid mapping was found.
+  PSID sid = nullptr;
+  fake_os_user_manager()->GetUserSID(OSUserManager::GetLocalDomain().c_str(),
+                                     kDefaultUsername, &sid);
+  ASSERT_NE(nullptr, sid);
+
+  // New user is created.
+  EXPECT_EQ(3ul, fake_os_user_manager()->GetUserCount());
+
+  ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    GaiaCredentialBaseCDSerialNumberFailureTest,
+    ::testing::Values(L"!@#!",        // All non alphanumeric characters
+                      L"serial#123",  // Contains non-alphanumeric chars.
+                      L"serial123!",  // Ends with non alphanumeric chars.
+                      L""));
+
 // Tests various sign in scenarios with consumer and non-consumer domains.
 // Parameters are:
 // 1. Is mdm enrollment enabled.
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
index ac2819c..ba377ec 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
@@ -438,7 +438,7 @@
     if (!AssociatedUserValidator::Get()->HasInternetConnection() &&
         !AssociatedUserValidator::Get()->IsOnlineLoginStale(sid)) {
       continue;
-    } else if (CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() &&
+    } else if (CGaiaCredentialBase::IsCloudAssociationEnabled() &&
                OSUserManager::Get()->IsUserDomainJoined(sid)) {
       if (user_id[0] && is_token_handle_valid_for_user) {
         continue;
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc
index 5c7cd804..b1cdc12 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_unittests.cc
@@ -454,7 +454,7 @@
 
 void GcpCredentialProviderWithGaiaUsersTest::SetUp() {
   GcpCredentialProviderTest::SetUp();
-  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(L"enable_ad_association", 0));
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(L"enable_cloud_association", 0));
 }
 
 // TODO(crbug.com/1038339): Test is failing consistently.
@@ -471,7 +471,7 @@
   CComBSTR sid;
   if (is_ad_user) {
     // Add an AD user. Note that this covers the scenario where
-    // enable_ad_association is set to false.
+    // enable_cloud_association is set to false.
     ASSERT_EQ(S_OK, fake_os_user_manager()->CreateTestOSUser(
                         L"username", L"password", L"full name", L"comment",
                         L"gaia-id", L"foo@gmail.com", L"domain", &sid));
@@ -549,7 +549,7 @@
 
 void GcpCredentialProviderWithADUsersTest::SetUp() {
   GcpCredentialProviderTest::SetUp();
-  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(L"enable_ad_association", 1));
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(L"enable_cloud_association", 1));
 }
 
 // TODO(crbug.com/1038351): Test fails on Windows.
diff --git a/chrome/credential_provider/gaiacp/gcp_utils.cc b/chrome/credential_provider/gaiacp/gcp_utils.cc
index c032c710..ae9e8a6 100644
--- a/chrome/credential_provider/gaiacp/gcp_utils.cc
+++ b/chrome/credential_provider/gaiacp/gcp_utils.cc
@@ -778,6 +778,35 @@
   return value && value->is_string() ? value->GetString() : std::string();
 }
 
+HRESULT SearchForListInStringDictUTF8(
+    const std::string& list_key,
+    const std::string& json_string,
+    const std::initializer_list<base::StringPiece>& path,
+    std::vector<std::string>* output) {
+  DCHECK(path.size() > 0);
+
+  base::Optional<base::Value> json_obj =
+      base::JSONReader::Read(json_string, base::JSON_ALLOW_TRAILING_COMMAS);
+  if (!json_obj || !json_obj->is_dict()) {
+    LOGFN(ERROR) << "base::JSONReader::Read failed to translate to JSON";
+    return E_FAIL;
+  }
+
+  auto* value = json_obj->FindListPath(base::JoinString(path, "."));
+  if (value && value->is_list()) {
+    base::Value::ListStorage& string_list = value->GetList();
+    for (const base::Value& entry : string_list) {
+      if (entry.FindKey(list_key) && entry.FindKey(list_key)->is_string()) {
+        std::string value = entry.FindKey(list_key)->GetString();
+        output->push_back(value);
+      } else {
+        return E_FAIL;
+      }
+    }
+  }
+  return S_OK;
+}
+
 std::string GetDictStringUTF8(const std::unique_ptr<base::Value>& dict,
                               const char* name) {
   return GetDictStringUTF8(*dict, name);
diff --git a/chrome/credential_provider/gaiacp/gcp_utils.h b/chrome/credential_provider/gaiacp/gcp_utils.h
index af8828d1..3a8564e 100644
--- a/chrome/credential_provider/gaiacp/gcp_utils.h
+++ b/chrome/credential_provider/gaiacp/gcp_utils.h
@@ -246,10 +246,23 @@
 // names provided in the input should be in order. Below is an example : Lets
 // say the json object is {"key1": {"key2": {"key3": "value1"}}, "key4":
 // "value2"}. Then to search for the key "key3", this method should be called
-// by providing the names vector as {"key1", "key2", "key3"}.
+// by providing the |path| as {"key1", "key2", "key3"}.
 std::string SearchForKeyInStringDictUTF8(
     const std::string& json_string,
     const std::initializer_list<base::StringPiece>& path);
+
+// Perform a recursive search on a nested dictionary object. Note that the
+// names provided in the input should be in order. Below is an example : Lets
+// say the json object is
+// {"key1": {"key2": {"value": "value1", "value": "value2"}}}.
+// Then to search for the key "key2" and list_key as "value", then this method
+// should be called by providing |list_key| as "value", |path| as
+// ["key1", "key2"] and the result returned would be ["value1", "value2"].
+HRESULT SearchForListInStringDictUTF8(
+    const std::string& list_key,
+    const std::string& json_string,
+    const std::initializer_list<base::StringPiece>& path,
+    std::vector<std::string>* output);
 std::string GetDictStringUTF8(const base::Value& dict, const char* name);
 std::string GetDictStringUTF8(const std::unique_ptr<base::Value>& dict,
                               const char* name);
diff --git a/chrome/credential_provider/gaiacp/reauth_credential.cc b/chrome/credential_provider/gaiacp/reauth_credential.cc
index 0d5e7e6..f0bae55 100644
--- a/chrome/credential_provider/gaiacp/reauth_credential.cc
+++ b/chrome/credential_provider/gaiacp/reauth_credential.cc
@@ -44,7 +44,7 @@
                                        OLE2CW(email_for_reauth_));
     }
     return CGaiaCredentialBase::GetUserGlsCommandline(command_line);
-  } else if (CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() &&
+  } else if (CGaiaCredentialBase::IsCloudAssociationEnabled() &&
              OSUserManager::Get()->IsUserDomainJoined(OLE2CW(os_user_sid_))) {
     // Note that if ADAssociationIsEnabled and the reauth credential is an AD
     // user account, then fallback to the GaiaCredentialBase for loading Gls.
@@ -99,7 +99,7 @@
     // If its an AD user sid without a user_id set in the registry, then
     // we need to show a different description message.
     if (email_for_reauth_.Length() == 0 &&
-        CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() &&
+        CGaiaCredentialBase::IsCloudAssociationEnabled() &&
         OSUserManager::Get()->IsUserDomainJoined(sid)) {
       description_label_id = IDS_REAUTH_AD_NO_USER_FID_DESCRIPTION_BASE;
     } else {
diff --git a/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc b/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
index a298199..0e2e25fb 100644
--- a/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
+++ b/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
@@ -93,9 +93,9 @@
   const bool is_user_domain_joined = std::get<2>(GetParam());
   const bool is_sid_empty = std::get<3>(GetParam());
 
-  // Override registry to enable AD association with google.
-  constexpr wchar_t kRegEnableADAssociation[] = L"enable_ad_association";
-  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegEnableADAssociation,
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation,
                                           is_ad_association_enabled));
 
   Microsoft::WRL::ComPtr<IReauthCredential> reauth;
@@ -332,9 +332,9 @@
 TEST_F(GcpReauthCredentialGlsRunnerTest, NoGaiaIdAvailableForADUser) {
   USES_CONVERSION;
 
-  // Override registry to enable AD association with google.
-  constexpr wchar_t kRegEnableADAssociation[] = L"enable_ad_association";
-  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegEnableADAssociation, 1));
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation, 1));
 
   CredentialProviderSigninDialogTestDataStorage test_data_storage;
 
diff --git a/chrome/renderer/extensions/extension_localization_peer_unittest.cc b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
index 96c8519c..4e22060e 100644
--- a/chrome/renderer/extensions/extension_localization_peer_unittest.cc
+++ b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
@@ -20,7 +20,6 @@
 #include "mojo/public/cpp/system/data_pipe_utils.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/redirect_info.h"
-#include "net/url_request/url_request_status.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -197,7 +196,7 @@
 
 MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; }
 
-TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) {
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLLoaderStatus) {
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
 
   // This test simulates completion before receiving the response header.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 25c7ed59..b4b0b3a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1161,7 +1161,6 @@
       "../browser/sessions/tab_restore_service_browsertest.cc",
       "../browser/sessions/tab_restore_service_load_waiter.cc",
       "../browser/sessions/tab_restore_service_load_waiter.h",
-      "../browser/signin/consistency_cookie_browsertest.cc",
       "../browser/signin/e2e_tests/live_sign_in_test.cc",
       "../browser/signin/e2e_tests/live_test.cc",
       "../browser/signin/e2e_tests/live_test.h",
@@ -1637,7 +1636,6 @@
         "../browser/apps/platform_apps/app_browsertest_util.h",
         "../browser/apps/platform_apps/audio_focus_web_contents_observer_browsertest.cc",
         "../browser/extensions/active_tab_apitest.cc",
-        "../browser/extensions/activity_log/activity_log_browsertest.cc",
         "../browser/extensions/alert_apitest.cc",
         "../browser/extensions/all_urls_apitest.cc",
         "../browser/extensions/api/activity_log_private/activity_log_private_apitest.cc",
diff --git a/chrome/test/base/web_ui_browser_test_browsertest.cc b/chrome/test/base/web_ui_browser_test_browsertest.cc
index b1a7abf..954a018 100644
--- a/chrome/test/base/web_ui_browser_test_browsertest.cc
+++ b/chrome/test/base/web_ui_browser_test_browsertest.cc
@@ -92,7 +92,8 @@
 }
 
 // Test times out in debug builds: https://crbug.com/902310
-#ifndef NDEBUG
+// Test also times out in Win7 Tests: https://crbug.com/1039406
+#if defined(OS_WIN) || !defined(NDEBUG)
 #define MAYBE_TestFailsAsyncFast DISABLED_TestFailsAsyncFast
 #else
 #define MAYBE_TestFailsAsyncFast TestFailsAsyncFast
diff --git a/chrome/test/data/prerender/prerender_deferred_sync_xhr.html b/chrome/test/data/prerender/prerender_deferred_sync_xhr.html
deleted file mode 100644
index 7028d53..0000000
--- a/chrome/test/data/prerender/prerender_deferred_sync_xhr.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<!--
-This test checks to make sure that deferred synchronous XHRs abort a prerender.
--->
-<head>
-<title>Prerender deferred synchronous XHR</title>
-<script>
-var xhr = new XMLHttpRequest();
-xhr.open("GET", "image-deferred.png", false);
-xhr.send();
-</script>
-
-</head>
-<body></body>
-</html>
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index e5e8171..01cb0b9 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -2150,7 +2150,13 @@
 // Printing doesn't work in content_browsertests.
 TEST_PPAPI_OUT_OF_PROCESS(Printing)
 
-TEST_PPAPI_NACL(MessageHandler)
+// https://crbug.com/1038957.
+#if defined(OS_LINUX)
+#define MAYBE_MessageHandler DISABLED_MessageHandler
+#else
+#define MAYBE_MessageHandler MessageHandler
+#endif
+TEST_PPAPI_NACL(MAYBE_MessageHandler)
 
 TEST_PPAPI_NACL(MessageLoop_Basics)
 TEST_PPAPI_NACL(MessageLoop_Post)
diff --git a/chromecast/media/BUILD.gn b/chromecast/media/BUILD.gn
index 59b3f85..29e12c0 100644
--- a/chromecast/media/BUILD.gn
+++ b/chromecast/media/BUILD.gn
@@ -90,6 +90,7 @@
     "//chromecast/media/audio:unittests",
     "//chromecast/media/audio/capture_service:unittests",
     "//chromecast/media/base:monotonic_clock",
+    "//chromecast/media/base:test_media_resource_tracker",
     "//chromecast/media/cma:test_support",
     "//chromecast/media/cma:unittests",
     "//chromecast/public",
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn
index e518c93f..da44bb4c 100644
--- a/chromecast/media/base/BUILD.gn
+++ b/chromecast/media/base/BUILD.gn
@@ -127,3 +127,17 @@
     "//base",
   ]
 }
+
+cast_source_set("test_media_resource_tracker") {
+  sources = [
+    "test_media_resource_tracker.cc",
+    "test_media_resource_tracker.h",
+  ]
+  deps = [
+    ":media_resource_tracker",
+    "//base",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+  testonly = true
+}
diff --git a/chromecast/media/base/media_resource_tracker.cc b/chromecast/media/base/media_resource_tracker.cc
index 13fc5c6..04c40f3 100644
--- a/chromecast/media/base/media_resource_tracker.cc
+++ b/chromecast/media/base/media_resource_tracker.cc
@@ -27,15 +27,15 @@
 }
 
 MediaResourceTracker::MediaResourceTracker(
-    const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner)
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> media_task_runner)
     : media_use_count_(0),
       media_lib_initialized_(false),
       delete_on_finalize_(false),
-      ui_task_runner_(ui_task_runner),
-      media_task_runner_(media_task_runner) {
-  DCHECK(ui_task_runner);
-  DCHECK(media_task_runner);
+      ui_task_runner_(std::move(ui_task_runner)),
+      media_task_runner_(std::move(media_task_runner)) {
+  DCHECK(ui_task_runner_);
+  DCHECK(media_task_runner_);
   DCHECK(ui_task_runner_->BelongsToCurrentThread());
 }
 
diff --git a/chromecast/media/base/media_resource_tracker.h b/chromecast/media/base/media_resource_tracker.h
index 639502c..3c3adb3 100644
--- a/chromecast/media/base/media_resource_tracker.h
+++ b/chromecast/media/base/media_resource_tracker.h
@@ -48,8 +48,8 @@
   };
 
   MediaResourceTracker(
-      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner);
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> media_task_runner);
 
   // Media resource acquire implementation. Must call on ui thread; runs
   // CastMediaShlib::Initialize on media thread.  Safe to call even if media lib
diff --git a/chromecast/media/base/media_resource_tracker_unittest.cc b/chromecast/media/base/media_resource_tracker_unittest.cc
index 68292bf8..29ba24c 100644
--- a/chromecast/media/base/media_resource_tracker_unittest.cc
+++ b/chromecast/media/base/media_resource_tracker_unittest.cc
@@ -9,49 +9,13 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
+#include "chromecast/media/base/test_media_resource_tracker.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromecast {
 namespace media {
 
-// Collection of mocks to verify MediaResourceTracker takes the correct actions.
-class MediaResourceTrackerTestMocks {
- public:
-  MOCK_METHOD0(Initialize, void());  // CastMediaShlib::Initialize
-  MOCK_METHOD0(Finalize, void());  // CastMediaShlib::Finalize
-  MOCK_METHOD0(Destroyed, void());  // ~CastMediaResourceTracker
-  MOCK_METHOD0(FinalizeCallback, void());  // callback to Finalize
-};
-
-class TestMediaResourceTracker : public MediaResourceTracker {
- public:
-  TestMediaResourceTracker(
-      MediaResourceTrackerTestMocks* test_mocks,
-      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner)
-      : MediaResourceTracker(ui_task_runner, media_task_runner),
-        test_mocks_(test_mocks) {}
-  ~TestMediaResourceTracker() override {
-    EXPECT_TRUE(ui_task_runner_->BelongsToCurrentThread());
-    test_mocks_->Destroyed();
-  }
-
-  void DoInitializeMediaLib() override {
-    ASSERT_TRUE(media_task_runner_->BelongsToCurrentThread());
-    test_mocks_->Initialize();
-  }
-  void DoFinalizeMediaLib() override {
-    ASSERT_TRUE(media_task_runner_->BelongsToCurrentThread());
-    test_mocks_->Finalize();
-  }
-
-  size_t media_use_count() const { return media_use_count_; }
-
- private:
-  MediaResourceTrackerTestMocks* test_mocks_;
-};
-
 class MediaResourceTrackerTest : public ::testing::Test {
  public:
   MediaResourceTrackerTest() {}
@@ -62,8 +26,8 @@
     test_mocks_.reset(new MediaResourceTrackerTestMocks());
 
     resource_tracker_ = new TestMediaResourceTracker(
-        test_mocks_.get(), task_environment_.GetMainThreadTaskRunner(),
-        task_environment_.GetMainThreadTaskRunner());
+        task_environment_.GetMainThreadTaskRunner(),
+        task_environment_.GetMainThreadTaskRunner(), test_mocks_.get());
   }
 
   void InitializeMediaLib() {
diff --git a/chromecast/media/base/test_media_resource_tracker.cc b/chromecast/media/base/test_media_resource_tracker.cc
new file mode 100644
index 0000000..a00969fa
--- /dev/null
+++ b/chromecast/media/base/test_media_resource_tracker.cc
@@ -0,0 +1,43 @@
+// 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 "chromecast/media/base/test_media_resource_tracker.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+
+MediaResourceTrackerTestMocks::MediaResourceTrackerTestMocks() = default;
+
+MediaResourceTrackerTestMocks::~MediaResourceTrackerTestMocks() = default;
+
+TestMediaResourceTracker::TestMediaResourceTracker(
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+    MediaResourceTrackerTestMocks* test_mocks)
+    : MediaResourceTracker(std::move(ui_task_runner),
+                           std::move(media_task_runner)),
+      test_mocks_(test_mocks) {}
+
+TestMediaResourceTracker::~TestMediaResourceTracker() {
+  EXPECT_TRUE(ui_task_runner_->BelongsToCurrentThread());
+  if (test_mocks_)
+    test_mocks_->Destroyed();
+}
+
+void TestMediaResourceTracker::DoInitializeMediaLib() {
+  ASSERT_TRUE(media_task_runner_->BelongsToCurrentThread());
+  if (test_mocks_)
+    test_mocks_->Initialize();
+}
+
+void TestMediaResourceTracker::DoFinalizeMediaLib() {
+  ASSERT_TRUE(media_task_runner_->BelongsToCurrentThread());
+  if (test_mocks_)
+    test_mocks_->Finalize();
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/base/test_media_resource_tracker.h b/chromecast/media/base/test_media_resource_tracker.h
new file mode 100644
index 0000000..23dbda2
--- /dev/null
+++ b/chromecast/media/base/test_media_resource_tracker.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Contains classes to aid in testing code that uses MediaResourceTracker.
+
+#ifndef CHROMECAST_MEDIA_BASE_TEST_MEDIA_RESOURCE_TRACKER_H_
+#define CHROMECAST_MEDIA_BASE_TEST_MEDIA_RESOURCE_TRACKER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "chromecast/media/base/media_resource_tracker.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromecast {
+namespace media {
+
+// Collection of mocks to verify MediaResourceTracker takes the correct actions.
+class MediaResourceTrackerTestMocks {
+ public:
+  MediaResourceTrackerTestMocks();
+  ~MediaResourceTrackerTestMocks();
+  MOCK_METHOD0(Initialize, void());
+  MOCK_METHOD0(Finalize, void());
+  MOCK_METHOD0(Destroyed, void());
+  MOCK_METHOD0(FinalizeCallback, void());
+};
+
+class TestMediaResourceTracker : public MediaResourceTracker {
+ public:
+  TestMediaResourceTracker(
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+      MediaResourceTrackerTestMocks* test_mocks);
+
+  ~TestMediaResourceTracker() override;
+
+  size_t media_use_count() const { return media_use_count_; }
+
+ private:
+  // MediaResourceTracker implementation:
+  void DoInitializeMediaLib() override;
+  void DoFinalizeMediaLib() override;
+
+  MediaResourceTrackerTestMocks* const test_mocks_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestMediaResourceTracker);
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_BASE_TEST_MEDIA_RESOURCE_TRACKER_H_
diff --git a/chromeos/components/help_app_ui/BUILD.gn b/chromeos/components/help_app_ui/BUILD.gn
index 9ae3e2e..7a1f3b4d 100644
--- a/chromeos/components/help_app_ui/BUILD.gn
+++ b/chromeos/components/help_app_ui/BUILD.gn
@@ -20,6 +20,7 @@
     "//chromeos/constants",
     "//chromeos/resources:help_app_bundle_resources",
     "//chromeos/resources:help_app_resources",
+    "//chromeos/system",
     "//content/public/browser",
     "//ui/resources:webui_resources_grd_grit",
     "//ui/webui",
diff --git a/chromeos/components/help_app_ui/help_app_guest_ui.cc b/chromeos/components/help_app_ui/help_app_guest_ui.cc
index 21b309d..2e503377 100644
--- a/chromeos/components/help_app_ui/help_app_guest_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_guest_ui.cc
@@ -9,6 +9,7 @@
 #include "chromeos/grit/chromeos_help_app_bundle_resources.h"
 #include "chromeos/grit/chromeos_help_app_bundle_resources_map.h"
 #include "chromeos/grit/chromeos_help_app_resources.h"
+#include "chromeos/system/statistics_provider.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/resources/grit/webui_resources.h"
 
@@ -30,6 +31,13 @@
 
   // Add strings that can be pulled in.
   source->AddString("boardName", base::SysInfo::GetLsbReleaseBoard());
+  source->AddString("chromeOSVersion", base::SysInfo::OperatingSystemVersion());
+  std::string customization_id;
+  chromeos::system::StatisticsProvider* provider =
+      chromeos::system::StatisticsProvider::GetInstance();
+  provider->GetMachineStatistic(chromeos::system::kCustomizationIdKey,
+                                &customization_id);
+  source->AddString("customizationId", customization_id);
   source->UseStringsJs();
 
   // TODO(crbug.com/1023700): Better solution before launch.
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt
index 3d0c3936..8eb5e0b 100644
--- a/chromeos/profiles/airmont.afdo.newest.txt
+++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-airmont-81-3987.18-1577702544-benchmark-81.0.4013.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-airmont-81-3987.18-1577702544-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/broadwell.afdo.newest.txt b/chromeos/profiles/broadwell.afdo.newest.txt
index bbcf255..54af3c8 100644
--- a/chromeos/profiles/broadwell.afdo.newest.txt
+++ b/chromeos/profiles/broadwell.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-broadwell-81-3987.18-1577704324-benchmark-81.0.4013.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-broadwell-81-3987.18-1577704324-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index 7281805b3..2f12a142 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-81-3987.18-1577705382-benchmark-81.0.4012.0-r1.orderfile.xz
\ No newline at end of file
+chromeos-chrome-orderfile-field-81-3987.18-1577705382-benchmark-81.0.4013.0-r1.orderfile.xz
\ No newline at end of file
diff --git a/chromeos/profiles/silvermont.afdo.newest.txt b/chromeos/profiles/silvermont.afdo.newest.txt
index 261fb51..3d369a5e 100644
--- a/chromeos/profiles/silvermont.afdo.newest.txt
+++ b/chromeos/profiles/silvermont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-silvermont-81-3987.18-1577705382-benchmark-81.0.4013.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-silvermont-81-3987.18-1577705382-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn
index 9fb5251..5913636 100644
--- a/components/autofill/android/BUILD.gn
+++ b/components/autofill/android/BUILD.gn
@@ -54,10 +54,14 @@
     "//components/autofill/core/common/mojom:mojo_types_java",
     "//content/public/android:content_java",
     "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//ui/android:ui_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = [
+    "java/src/org/chromium/components/autofill/AutofillManagerWrapper.java",
     "java/src/org/chromium/components/autofill/AutofillProvider.java",
+    "java/src/org/chromium/components/autofill/AutofillProviderImpl.java",
+    "java/src/org/chromium/components/autofill/AutofillProviderUMA.java",
     "java/src/org/chromium/components/autofill/FormData.java",
     "java/src/org/chromium/components/autofill/FormFieldData.java",
   ]
diff --git a/components/autofill/android/OWNERS b/components/autofill/android/OWNERS
index fcd1c786a..7f956d0 100644
--- a/components/autofill/android/OWNERS
+++ b/components/autofill/android/OWNERS
@@ -1 +1,8 @@
 file://ui/android/OWNERS
+
+# Files related to integration with system autofill
+per-file *autofill_provider*=michaelbai@chromium.org
+per-file *AutofillProvider*=michaelbai@chromium.org
+per-file *AutofillManagerWrapper*=michaelbai@chromium.org
+per-file *form*=michaelbai@chromium.org
+per-file *Form*=michaelbai@chromium.org
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
similarity index 87%
rename from android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
rename to components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
index e02827da..04224de 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.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.android_webview;
+package org.chromium.components.autofill;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -24,8 +24,10 @@
  * The class to call Android's AutofillManager.
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class AwAutofillManager {
+public class AutofillManagerWrapper {
     // Don't change TAG, it is used for runtime log.
+    // NOTE: As a result of the above, the tag below still references the name of this class from
+    // when it was originally developed specifically for Android WebView.
     public static final String TAG = "AwAutofillManager";
 
     /**
@@ -34,15 +36,15 @@
     public static interface InputUIObserver { void onInputUIShown(); }
 
     private static class AutofillInputUIMonitor extends AutofillManager.AutofillCallback {
-        private WeakReference<AwAutofillManager> mManager;
+        private WeakReference<AutofillManagerWrapper> mManager;
 
-        public AutofillInputUIMonitor(AwAutofillManager manager) {
-            mManager = new WeakReference<AwAutofillManager>(manager);
+        public AutofillInputUIMonitor(AutofillManagerWrapper manager) {
+            mManager = new WeakReference<AutofillManagerWrapper>(manager);
         }
 
         @Override
         public void onAutofillEvent(View view, int virtualId, int event) {
-            AwAutofillManager manager = mManager.get();
+            AutofillManagerWrapper manager = mManager.get();
             if (manager == null) return;
             manager.mIsAutofillInputUIShowing = (event == EVENT_INPUT_SHOWN);
             if (event == EVENT_INPUT_SHOWN) manager.notifyInputUIChange();
@@ -57,7 +59,7 @@
     private boolean mDisabled;
     private ArrayList<WeakReference<InputUIObserver>> mInputUIObservers;
 
-    public AwAutofillManager(Context context) {
+    public AutofillManagerWrapper(Context context) {
         updateLogStat();
         if (isLoggable()) log("constructor");
         mAutofillManager = context.getSystemService(AutofillManager.class);
@@ -92,9 +94,7 @@
     public void notifyVirtualViewEntered(View parent, int childId, Rect absBounds) {
         // Log warning only when the autofill is triggered.
         if (mDisabled) {
-            Log.w(TAG,
-                    "WebView autofill is disabled because WebView isn't created with "
-                            + "activity context.");
+            Log.w(TAG, "Autofill is disabled: AutofillManager isn't available in given Context.");
             return;
         }
         if (checkAndWarnIfDestroyed()) return;
@@ -134,7 +134,7 @@
 
     private boolean checkAndWarnIfDestroyed() {
         if (mDestroyed) {
-            Log.w(TAG, "Application attempted to call on a destroyed AwAutofillManager",
+            Log.w(TAG, "Application attempted to call on a destroyed AutofillManagerWrapper",
                     new Throwable());
         }
         return mDestroyed;
@@ -190,6 +190,7 @@
 
     private static void updateLogStat() {
         // Use 'setprop log.tag.AwAutofillManager DEBUG' to enable the log at runtime.
+        // NOTE: See the comment on TAG above for why this is still AwAutofillManager.
         sIsLoggable = Log.isLoggable(TAG, Log.DEBUG);
     }
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java
similarity index 92%
rename from android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
rename to components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java
index 1510c44..a010f18 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.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.android_webview;
+package org.chromium.components.autofill;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -21,9 +21,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.DoNotInline;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
-import org.chromium.components.autofill.AutofillProvider;
-import org.chromium.components.autofill.FormData;
-import org.chromium.components.autofill.FormFieldData;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.display.DisplayAndroid;
@@ -32,16 +29,17 @@
  * This class uses Android autofill service to fill web form. All methods are
  * supposed to be called in UI thread.
  *
- * This class doesn't have 1:1 mapping to native AutofillProviderAndroid and is
- * same as how AwContents.java mapping to native AwContents, AwAutofillProvider
- * is owned by AwContents.java and AutofillProviderAndroid is owned by native
- * AwContents.
+ * This class doesn't have 1:1 mapping to native AutofillProviderAndroid; the
+ * normal ownership model is that this object is owned by the embedder-specific
+ * Java WebContents wrapper (e.g., AwContents.java in //android_webview), and
+ * AutofillProviderAndroid is owned by the embedder-specific C++ WebContents
+ * wrapper (e.g., native AwContents in //android_webview).
  *
  * DoNotInline since it causes class verification errors, see crbug.com/991851.
  */
 @DoNotInline
 @TargetApi(Build.VERSION_CODES.O)
-public class AwAutofillProvider extends AutofillProvider {
+public class AutofillProviderImpl extends AutofillProvider {
     private static class FocusField {
         public final short fieldIndex;
         public final Rect absBound;
@@ -216,28 +214,30 @@
         }
     }
 
-    private AwAutofillManager mAutofillManager;
+    private AutofillManagerWrapper mAutofillManager;
     private ViewGroup mContainerView;
     private WebContents mWebContents;
 
     private AutofillRequest mRequest;
     private long mNativeAutofillProvider;
-    private AwAutofillUMA mAutofillUMA;
-    private AwAutofillManager.InputUIObserver mInputUIObserver;
+    private AutofillProviderUMA mAutofillUMA;
+    private AutofillManagerWrapper.InputUIObserver mInputUIObserver;
     private long mAutofillTriggeredTimeMillis;
 
-    public AwAutofillProvider(Context context, ViewGroup containerView) {
-        this(containerView, new AwAutofillManager(context), context);
+    public AutofillProviderImpl(Context context, ViewGroup containerView) {
+        this(containerView, new AutofillManagerWrapper(context), context);
     }
 
     @VisibleForTesting
-    public AwAutofillProvider(ViewGroup containerView, AwAutofillManager manager, Context context) {
-        try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped("AwAutofillProvider.constructor")) {
+    public AutofillProviderImpl(
+            ViewGroup containerView, AutofillManagerWrapper manager, Context context) {
+        try (ScopedSysTraceEvent e =
+                        ScopedSysTraceEvent.scoped("AutofillProviderImpl.constructor")) {
             assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
             mAutofillManager = manager;
             mContainerView = containerView;
-            mAutofillUMA = new AwAutofillUMA(context);
-            mInputUIObserver = new AwAutofillManager.InputUIObserver() {
+            mAutofillUMA = new AutofillProviderUMA(context);
+            mInputUIObserver = new AutofillManagerWrapper.InputUIObserver() {
                 @Override
                 public void onInputUIShown() {
                     // Not need to report suggestion window displayed if there is no live autofill
@@ -259,12 +259,12 @@
     @Override
     public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
         // This method could be called for the session started by the native
-        // control outside of WebView, e.g. the URL bar, in this case, we simply
+        // control outside of the scope of autofill, e.g. the URL bar, in this case, we simply
         // return.
         if (mRequest == null) return;
         mRequest.fillViewStructure(structure);
-        if (AwAutofillManager.isLoggable()) {
-            AwAutofillManager.log(
+        if (AutofillManagerWrapper.isLoggable()) {
+            AutofillManagerWrapper.log(
                     "onProvideAutoFillVirtualStructure fields:" + structure.getChildCount());
         }
         mAutofillUMA.onVirtualStructureProvided();
@@ -274,8 +274,8 @@
     public void autofill(final SparseArray<AutofillValue> values) {
         if (mNativeAutofillProvider != 0 && mRequest != null && mRequest.autofill((values))) {
             autofill(mNativeAutofillProvider, mRequest.mFormData);
-            if (AwAutofillManager.isLoggable()) {
-                AwAutofillManager.log("autofill values:" + values.size());
+            if (AutofillManagerWrapper.isLoggable()) {
+                AutofillManagerWrapper.log("autofill values:" + values.size());
             }
             mAutofillUMA.onAutofill();
         }
@@ -300,7 +300,7 @@
     public void startAutofillSession(
             FormData formData, int focus, float x, float y, float width, float height) {
         // Check focusField inside short value?
-        // Autofill Manager might have session that wasn't started by WebView,
+        // Autofill Manager might have session that wasn't started by AutofillProviderImpl,
         // we just always cancel existing session here.
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
             mAutofillManager.cancel();
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillUMA.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.java
similarity index 86%
rename from android_webview/java/src/org/chromium/android_webview/AwAutofillUMA.java
rename to components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.java
index 4491855..394cd84 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillUMA.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.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.android_webview;
+package org.chromium.components.autofill;
 
 import android.content.Context;
 
@@ -13,20 +13,22 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * The class for WebView autofill UMA.
+ * The class for AutofillProvider-related UMA. Note that most of the concrete histogram
+ * names include "WebView"; when this class was originally developed it was WebView-specific,
+ * and when generalizing it we did not change these names to maintain continuity when
+ * analyzing the histograms.
  */
-public class AwAutofillUMA {
+public class AutofillProviderUMA {
     // Records whether the Autofill service is enabled or not.
-    public static final String UMA_AUTOFILL_WEBVIEW_ENABLED = "Autofill.WebView.Enabled";
+    public static final String UMA_AUTOFILL_ENABLED = "Autofill.WebView.Enabled";
 
     // Records whether the Autofill provider is created by activity context or not.
-    public static final String UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT =
+    public static final String UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT =
             "Autofill.WebView.CreatedByActivityContext";
 
     // Records what happened in an autofill session.
-    public static final String UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION =
-            "Autofill.WebView.AutofillSession";
-    // The possible value of UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION.
+    public static final String UMA_AUTOFILL_AUTOFILL_SESSION = "Autofill.WebView.AutofillSession";
+    // The possible value of UMA_AUTOFILL_AUTOFILL_SESSION.
     public static final int SESSION_UNKNOWN = 0;
     public static final int NO_CALLBACK_FORM_FRAMEWORK = 1;
     public static final int NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED = 2;
@@ -48,9 +50,8 @@
     public static final String UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD =
             "Autofill.WebView.UserChangedAutofilledField";
 
-    public static final String UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE =
-            "Autofill.WebView.SubmissionSource";
-    // The possible value of UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE.
+    public static final String UMA_AUTOFILL_SUBMISSION_SOURCE = "Autofill.WebView.SubmissionSource";
+    // The possible value of UMA_AUTOFILL_SUBMISSION_SOURCE.
     public static final int SAME_DOCUMENT_NAVIGATION = 0;
     public static final int XHR_SUCCEEDED = 1;
     public static final int FRAME_DETACHED = 2;
@@ -59,13 +60,11 @@
     public static final int FORM_SUBMISSION = 5;
     public static final int SUBMISSION_SOURCE_HISTOGRAM_COUNT = 6;
 
-    // The million seconds from user touched the field to WebView started autofill session.
-    public static final String UMA_AUTOFILL_WEBVIEW_TRIGGERING_TIME =
-            "Autofill.WebView.TriggeringTime";
+    // The million seconds from user touched the field to the autofill session starting.
+    public static final String UMA_AUTOFILL_TRIGGERING_TIME = "Autofill.WebView.TriggeringTime";
 
-    // The million seconds from WebView started autofill session to suggestion was displayed.
-    public static final String UMA_AUTOFILL_WEBVIEW_SUGGESTION_TIME =
-            "Autofill.WebView.SuggestionTime";
+    // The million seconds from the autofill session starting to the suggestion being displayed.
+    public static final String UMA_AUTOFILL_SUGGESTION_TIME = "Autofill.WebView.SuggestionTime";
 
     // The expected time range of time is from 10ms to 2 seconds, and 50 buckets is sufficient.
     private static final long MIN_TIME_MILLIS = 10;
@@ -111,7 +110,7 @@
         }
 
         public void recordHistogram() {
-            RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION,
+            RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_AUTOFILL_SESSION,
                     toUMAAutofillSessionValue(), AUTOFILL_SESSION_HISTOGRAM_COUNT);
             // Only record if user ever changed form.
             if (mUserChangedAutofilledField != null) {
@@ -119,7 +118,7 @@
                         UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, mUserChangedAutofilledField);
             }
             if (mSuggestionTimeMillis != null) {
-                recordTimesHistogram(UMA_AUTOFILL_WEBVIEW_SUGGESTION_TIME, mSuggestionTimeMillis);
+                recordTimesHistogram(UMA_AUTOFILL_SUGGESTION_TIME, mSuggestionTimeMillis);
             }
         }
 
@@ -180,8 +179,8 @@
     private SessionRecorder mRecorder;
     private Boolean mAutofillDisabled;
 
-    public AwAutofillUMA(Context context) {
-        RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT,
+    public AutofillProviderUMA(Context context) {
+        RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT,
                 ContextUtils.activityFromContext(context) != null);
     }
 
@@ -189,14 +188,14 @@
         if (mRecorder != null) mRecorder.record(SessionRecorder.EVENT_FORM_SUBMITTED);
         recordSession();
         // We record this no matter autofill service is disabled or not.
-        RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE,
+        RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_SUBMISSION_SOURCE,
                 toUMASubmissionSource(submissionSource), SUBMISSION_SOURCE_HISTOGRAM_COUNT);
     }
 
     public void onSessionStarted(boolean autofillDisabled) {
         // Record autofill status once per instance and only if user triggers the autofill.
         if (mAutofillDisabled == null || mAutofillDisabled.booleanValue() != autofillDisabled) {
-            RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_WEBVIEW_ENABLED, !autofillDisabled);
+            RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_ENABLED, !autofillDisabled);
             mAutofillDisabled = Boolean.valueOf(autofillDisabled);
         }
 
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn
index 9f3f0f3..4b71f2d4 100644
--- a/components/browser_ui/widget/android/BUILD.gn
+++ b/components/browser_ui/widget/android/BUILD.gn
@@ -10,6 +10,12 @@
     "java/src/org/chromium/components/browser_ui/widget/BoundedLinearLayout.java",
     "java/src/org/chromium/components/browser_ui/widget/DualControlLayout.java",
     "java/src/org/chromium/components/browser_ui/widget/FadingEdgeScrollView.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserver.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserverAdapter.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/HorizontalDisplayStyle.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/UiConfig.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/VerticalDisplayStyle.java",
+    "java/src/org/chromium/components/browser_ui/widget/displaystyle/ViewResizer.java",
     "java/src/org/chromium/components/browser_ui/widget/text/AccessibleTextView.java",
     "java/src/org/chromium/components/browser_ui/widget/text/AlertDialogEditText.java",
     "java/src/org/chromium/components/browser_ui/widget/text/TemplatePreservingTextView.java",
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserver.java
similarity index 87%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserver.java
index 6fdaa91..52956a1 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserver.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 /**
  * Gets notified of changes in the display style.
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserverAdapter.java
similarity index 97%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserverAdapter.java
index 1ea95501..a0c0179 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/DisplayStyleObserverAdapter.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 import android.view.View;
 
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/HorizontalDisplayStyle.java
similarity index 89%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/HorizontalDisplayStyle.java
index a0c45cd..f05c4c0 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/HorizontalDisplayStyle.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 import androidx.annotation.IntDef;
 
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/OWNERS b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/OWNERS
similarity index 100%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/OWNERS
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/OWNERS
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/UiConfig.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/UiConfig.java
similarity index 98%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/UiConfig.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/UiConfig.java
index 7dca1352..af7d64c4 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/UiConfig.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/UiConfig.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 import android.content.Context;
 import android.view.View;
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/VerticalDisplayStyle.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/VerticalDisplayStyle.java
similarity index 88%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/VerticalDisplayStyle.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/VerticalDisplayStyle.java
index 645998b0..40a9add 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/VerticalDisplayStyle.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/VerticalDisplayStyle.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 import androidx.annotation.IntDef;
 
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/ViewResizer.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/ViewResizer.java
similarity index 98%
rename from chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/ViewResizer.java
rename to components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/ViewResizer.java
index 77f25ce..f8d75d46 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/displaystyle/ViewResizer.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/displaystyle/ViewResizer.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.ui.widget.displaystyle;
+package org.chromium.components.browser_ui.widget.displaystyle;
 
 import android.content.res.Resources;
 import android.support.v4.view.ViewCompat;
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc
index 4494c00..313cd30 100644
--- a/components/exo/wayland/clients/client_base.cc
+++ b/components/exo/wayland/clients/client_base.cc
@@ -165,12 +165,6 @@
 wl_buffer_listener g_buffer_listener = {BufferRelease};
 
 #if defined(USE_GBM)
-const GrGLInterface* GrGLCreateNativeInterface() {
-  return GrGLAssembleInterface(nullptr, [](void* ctx, const char name[]) {
-    return eglGetProcAddress(name);
-  });
-}
-
 #if defined(USE_VULKAN)
 uint32_t VulkanChooseGraphicsQueueFamily(VkPhysicalDevice device) {
   uint32_t properties_number = 0;
@@ -446,7 +440,6 @@
   }
 
 #if defined(USE_GBM)
-  sk_sp<const GrGLInterface> native_interface;
   if (params.use_drm) {
     // Number of files to look for when discovering DRM devices.
     const uint32_t kDrmMaxMinor = 15;
@@ -504,7 +497,9 @@
       egl_sync_type_ = EGL_SYNC_NATIVE_FENCE_ANDROID;
     }
 
-    native_interface = sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
+    sk_sp<const GrGLInterface> native_interface = GrGLMakeAssembledInterface(
+        nullptr,
+        [](void* ctx, const char name[]) { return eglGetProcAddress(name); });
     DCHECK(native_interface);
     gr_context_ = GrContext::MakeGL(std::move(native_interface));
     DCHECK(gr_context_);
diff --git a/components/metrics/call_stack_profile_builder.cc b/components/metrics/call_stack_profile_builder.cc
index e0c900e..124ffd70a 100644
--- a/components/metrics/call_stack_profile_builder.cc
+++ b/components/metrics/call_stack_profile_builder.cc
@@ -87,13 +87,16 @@
 }
 
 void CallStackProfileBuilder::OnSampleCompleted(
-    std::vector<base::Frame> frames) {
-  OnSampleCompleted(std::move(frames), 1, 1);
+    std::vector<base::Frame> frames,
+    base::TimeTicks sample_timestamp) {
+  OnSampleCompleted(std::move(frames), sample_timestamp, 1, 1);
 }
 
-void CallStackProfileBuilder::OnSampleCompleted(std::vector<base::Frame> frames,
-                                                size_t weight,
-                                                size_t count) {
+void CallStackProfileBuilder::OnSampleCompleted(
+    std::vector<base::Frame> frames,
+    base::TimeTicks sample_timestamp,
+    size_t weight,
+    size_t count) {
   // Write CallStackProfile::Stack protobuf message.
   CallStackProfile::Stack stack;
 
diff --git a/components/metrics/call_stack_profile_builder.h b/components/metrics/call_stack_profile_builder.h
index dc020df..2326c13 100644
--- a/components/metrics/call_stack_profile_builder.h
+++ b/components/metrics/call_stack_profile_builder.h
@@ -66,6 +66,7 @@
 
   // Both weight and count are used by the heap profiler only.
   void OnSampleCompleted(std::vector<base::Frame> frames,
+                         base::TimeTicks sample_timestamp,
                          size_t weight,
                          size_t count);
 
@@ -73,7 +74,8 @@
   base::ModuleCache* GetModuleCache() override;
   void RecordMetadata(
       base::ProfileBuilder::MetadataProvider* metadata_provider) override;
-  void OnSampleCompleted(std::vector<base::Frame> frames) override;
+  void OnSampleCompleted(std::vector<base::Frame> frames,
+                         base::TimeTicks sample_timestamp) override;
   void OnProfileCompleted(base::TimeDelta profile_duration,
                           base::TimeDelta sampling_period) override;
 
diff --git a/components/metrics/call_stack_profile_builder_unittest.cc b/components/metrics/call_stack_profile_builder_unittest.cc
index 7a9d47c1..b9b3ca5 100644
--- a/components/metrics/call_stack_profile_builder_unittest.cc
+++ b/components/metrics/call_stack_profile_builder_unittest.cc
@@ -118,10 +118,10 @@
 
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames1);
+  profile_builder->OnSampleCompleted(frames1, base::TimeTicks());
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames2);
+  profile_builder->OnSampleCompleted(frames2, base::TimeTicks());
   profile_builder->OnProfileCompleted(base::TimeDelta::FromMilliseconds(500),
                                       base::TimeDelta::FromMilliseconds(100));
 
@@ -183,9 +183,9 @@
   base::Frame frame1 = {0x10, &module1};
   std::vector<base::Frame> frames = {frame1};
 
-  profile_builder->OnSampleCompleted(frames, 42, 3);
-  profile_builder->OnSampleCompleted(frames, 1, 1);
-  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks(), 42, 3);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks(), 1, 1);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks());
   profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
 
   const SampledProfile& proto = profile_builder->test_sampled_profile();
@@ -219,10 +219,10 @@
   // to one.
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks());
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks());
 
   profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
 
@@ -259,10 +259,10 @@
   // Two stacks are completed with the different frames therefore not deduped.
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames1);
+  profile_builder->OnSampleCompleted(frames1, base::TimeTicks());
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames2);
+  profile_builder->OnSampleCompleted(frames2, base::TimeTicks());
 
   profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
 
@@ -305,7 +305,7 @@
 
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks());
   profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
 
   const SampledProfile& proto = profile_builder->test_sampled_profile();
@@ -356,7 +356,7 @@
 
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnSampleCompleted(frames, base::TimeTicks());
   profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
 
   const SampledProfile& proto = profile_builder->test_sampled_profile();
@@ -408,25 +408,25 @@
   // not have continued_work set.
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
 
   // The second sample with the same id should have continued_work set.
   work_id_recorder.current_id = 1;
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
 
   // Ids are in general non-contiguous across multiple samples.
   work_id_recorder.current_id = 10;
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
   profile_builder->RecordMetadata(
       base::MetadataRecorder().CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
 
   profile_builder->OnProfileCompleted(base::TimeDelta::FromMilliseconds(500),
                                       base::TimeDelta::FromMilliseconds(100));
@@ -458,7 +458,7 @@
   metadata_recorder.Set(100, base::nullopt, 10);
   profile_builder->RecordMetadata(
       metadata_recorder.CreateMetadataProvider().get());
-  profile_builder->OnSampleCompleted({frame});
+  profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
 
   profile_builder->OnProfileCompleted(base::TimeDelta::FromMilliseconds(500),
                                       base::TimeDelta::FromMilliseconds(100));
diff --git a/components/minidump_uploader/BUILD.gn b/components/minidump_uploader/BUILD.gn
index cc406b20..a0f823b7 100644
--- a/components/minidump_uploader/BUILD.gn
+++ b/components/minidump_uploader/BUILD.gn
@@ -37,10 +37,10 @@
     "android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java",
     "android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java",
     "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java",
+    "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJob.java",
+    "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImpl.java",
     "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobService.java",
-    "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java",
     "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploaderDelegate.java",
-    "android/java/src/org/chromium/components/minidump_uploader/MinidumpUploaderImpl.java",
     "android/java/src/org/chromium/components/minidump_uploader/util/CrashReportingPermissionManager.java",
     "android/java/src/org/chromium/components/minidump_uploader/util/HttpURLConnectionFactory.java",
     "android/java/src/org/chromium/components/minidump_uploader/util/HttpURLConnectionFactoryImpl.java",
@@ -62,9 +62,9 @@
     "android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java",
     "android/javatests/src/org/chromium/components/minidump_uploader/CrashTestRule.java",
     "android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java",
+    "android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImplTest.java",
     "android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java",
-    "android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploaderImplTest.java",
+    "android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploadJobImpl.java",
     "android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderDelegate.java",
-    "android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderImpl.java",
   ]
 }
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJob.java
similarity index 96%
rename from components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java
rename to components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJob.java
index b0065de..8716228 100644
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploader.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJob.java
@@ -7,7 +7,7 @@
 /**
  * Interface for uploading minidumps.
  */
-public interface MinidumpUploader {
+public interface MinidumpUploadJob {
     /**
      * Try to upload all the minidumps in the crash directory.
      * This method will be called on the UI thread of our JobService.
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploaderImpl.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImpl.java
similarity index 93%
rename from components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploaderImpl.java
rename to components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImpl.java
index 4eddfdc..73636b1 100644
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploaderImpl.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImpl.java
@@ -20,8 +20,8 @@
  * successfully uploaded any minidumps. At the end of a job it simply checks whether there are any
  * minidumps left to upload, and if so, the job is rescheduled.
  */
-public class MinidumpUploaderImpl implements MinidumpUploader {
-    private static final String TAG = "MinidumpUploaderImpl";
+public class MinidumpUploadJobImpl implements MinidumpUploadJob {
+    private static final String TAG = "MDUploadJobImpl";
 
     /**
      * The delegate that performs embedder-specific behavior.
@@ -44,7 +44,7 @@
     public static final int MAX_UPLOAD_TRIES_ALLOWED = 3;
 
     @VisibleForTesting
-    public MinidumpUploaderImpl(MinidumpUploaderDelegate delegate) {
+    public MinidumpUploadJobImpl(MinidumpUploaderDelegate delegate) {
         mDelegate = delegate;
     }
 
@@ -74,9 +74,9 @@
      * to the worker thread.
      */
     private class UploadRunnable implements Runnable {
-        private final MinidumpUploader.UploadsFinishedCallback mUploadsFinishedCallback;
+        private final MinidumpUploadJob.UploadsFinishedCallback mUploadsFinishedCallback;
 
-        public UploadRunnable(MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
+        public UploadRunnable(MinidumpUploadJob.UploadsFinishedCallback uploadsFinishedCallback) {
             mUploadsFinishedCallback = uploadsFinishedCallback;
         }
 
@@ -159,14 +159,14 @@
 
     @Override
     public void uploadAllMinidumps(
-            final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
+            final MinidumpUploadJob.UploadsFinishedCallback uploadsFinishedCallback) {
         ThreadUtils.assertOnUiThread();
         if (mWorkerThread != null) {
             throw new RuntimeException(
-                    "A given minidump uploader instance should never be launched more than once.");
+                    "A given minidump upload job instance should never be launched more than once.");
         }
         mWorkerThread = new Thread(
-                new UploadRunnable(uploadsFinishedCallback), "MinidumpUploader-WorkerThread");
+                new UploadRunnable(uploadsFinishedCallback), "MinidumpUploadJob-WorkerThread");
         mCancelUpload = false;
 
         mDelegate.prepareToUploadMinidumps(new Runnable() {
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobService.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobService.java
index 7472c3e..abbcb96 100644
--- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobService.java
+++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadJobService.java
@@ -32,7 +32,7 @@
     // Back-off policy for upload-job.
     private static final int JOB_BACKOFF_POLICY = JobInfo.BACKOFF_POLICY_EXPONENTIAL;
 
-    private MinidumpUploader mMinidumpUploader;
+    private MinidumpUploadJob mMinidumpUploadJob;
 
     // Used in Debug builds to assert that this job service never attempts to run more than one job
     // at a time:
@@ -65,15 +65,15 @@
             assert !mRunningJob;
             mRunningJob = true;
         }
-        mMinidumpUploader = createMinidumpUploader(params.getExtras());
-        mMinidumpUploader.uploadAllMinidumps(createJobFinishedCallback(params));
+        mMinidumpUploadJob = createMinidumpUploadJob(params.getExtras());
+        mMinidumpUploadJob.uploadAllMinidumps(createJobFinishedCallback(params));
         return true; // true = processing work on a separate thread, false = done already.
     }
 
     @Override
     public boolean onStopJob(JobParameters params) {
         Log.i(TAG, "Canceling pending uploads due to change in networking status.");
-        boolean reschedule = mMinidumpUploader.cancelUploads();
+        boolean reschedule = mMinidumpUploadJob.cancelUploads();
         synchronized (mRunningLock) {
             mRunningJob = false;
         }
@@ -82,13 +82,13 @@
 
     @Override
     public void onDestroy() {
-        mMinidumpUploader = null;
+        mMinidumpUploadJob = null;
         super.onDestroy();
     }
 
-    private MinidumpUploader.UploadsFinishedCallback createJobFinishedCallback(
+    private MinidumpUploadJob.UploadsFinishedCallback createJobFinishedCallback(
             final JobParameters params) {
-        return new MinidumpUploader.UploadsFinishedCallback() {
+        return new MinidumpUploadJob.UploadsFinishedCallback() {
             @Override
             public void uploadsFinished(boolean reschedule) {
                 if (reschedule) {
@@ -103,8 +103,12 @@
     }
 
     /**
+     * Create a MinidumpUploadJob instance that implements required logic for uploading minidumps
+     * based upon data (generally containing permission information) captured at the time the job
+     * was scheduled.
+     *
      * @param extras Any extra data persisted for this job.
-     * @return The minidump uploader that jobs should use.
+     * @return The minidump upload job that jobs should use to manage minidump uploading.
      */
-    protected abstract MinidumpUploader createMinidumpUploader(PersistableBundle extras);
+    protected abstract MinidumpUploadJob createMinidumpUploadJob(PersistableBundle extras);
 }
diff --git a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploaderImplTest.java b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImplTest.java
similarity index 85%
rename from components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploaderImplTest.java
rename to components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImplTest.java
index 4a1fc34c..5404cc1 100644
--- a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploaderImplTest.java
+++ b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadJobImplTest.java
@@ -29,11 +29,11 @@
 import java.util.concurrent.CountDownLatch;
 
 /**
- * Instrumentation tests for the common MinidumpUploader implementation within the minidump_uploader
- * component.
+ * Instrumentation tests for the common MinidumpUploadJob implementation within the
+ * minidump_uploader component.
  */
 @RunWith(BaseJUnit4ClassRunner.class)
-public class MinidumpUploaderImplTest {
+public class MinidumpUploadJobImplTest {
     @Rule
     public CrashTestRule mTestRule = new CrashTestRule();
 
@@ -55,13 +55,13 @@
                         mIsEnabledForTests = false;
                     }
                 };
-        MinidumpUploader minidumpUploader =
-                new TestMinidumpUploaderImpl(mTestRule.getExistingCacheDir(), permManager);
+        MinidumpUploadJob minidumpUploadJob =
+                new TestMinidumpUploadJobImpl(mTestRule.getExistingCacheDir(), permManager);
 
         File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0.try0");
         File secondFile = createMinidumpFileInCrashDir("12_abc.dmp0.try0");
-        String triesBelowMaxString = ".try" + (MinidumpUploaderImpl.MAX_UPLOAD_TRIES_ALLOWED - 1);
-        String maxTriesString = ".try" + MinidumpUploaderImpl.MAX_UPLOAD_TRIES_ALLOWED;
+        String triesBelowMaxString = ".try" + (MinidumpUploadJobImpl.MAX_UPLOAD_TRIES_ALLOWED - 1);
+        String maxTriesString = ".try" + MinidumpUploadJobImpl.MAX_UPLOAD_TRIES_ALLOWED;
         File justBelowMaxTriesFile =
                 createMinidumpFileInCrashDir("belowmaxtries.dmp0" + triesBelowMaxString);
         File maxTriesFile = createMinidumpFileInCrashDir("maxtries.dmp0" + maxTriesString);
@@ -72,7 +72,7 @@
                 justBelowMaxTriesFile.getName().replace(triesBelowMaxString, maxTriesString));
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, true /* expectReschedule */);
+                minidumpUploadJob, true /* expectReschedule */);
         Assert.assertFalse(firstFile.exists());
         Assert.assertFalse(secondFile.exists());
         Assert.assertFalse(justBelowMaxTriesFile.exists());
@@ -105,14 +105,14 @@
                         new MinidumpUploadCallableTest.TestHttpURLConnectionFactory(), permManager);
             }
         });
-        MinidumpUploader minidumpUploader = createCallableListMinidumpUploader(
+        MinidumpUploadJob minidumpUploadJob = createCallableListMinidumpUploadJob(
                 callables, permManager.isUsageAndCrashReportingPermittedByUser());
 
         File firstFile = createMinidumpFileInCrashDir("firstFile.dmp0.try0");
         File secondFile = createMinidumpFileInCrashDir("secondFile.dmp0.try0");
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, true /* expectReschedule */);
+                minidumpUploadJob, true /* expectReschedule */);
         Assert.assertFalse(firstFile.exists());
         Assert.assertFalse(secondFile.exists());
         File expectedSecondFile;
@@ -135,14 +135,14 @@
     @Test
     @MediumTest
     public void testInvalidMinidumpNameGeneratesNoUploads() throws IOException {
-        MinidumpUploader minidumpUploader =
-                new ExpectNoUploadsMinidumpUploaderImpl(mTestRule.getExistingCacheDir());
+        MinidumpUploadJob minidumpUploadJob =
+                new ExpectNoUploadsMinidumpUploadJobImpl(mTestRule.getExistingCacheDir());
 
         // Note the omitted ".try0" suffix.
         File fileUsingLegacyNamingScheme = createMinidumpFileInCrashDir("1_abc.dmp0");
 
         MinidumpUploadTestUtility.uploadMinidumpsSync(
-                minidumpUploader, false /* expectReschedule */);
+                minidumpUploadJob, false /* expectReschedule */);
 
         // The file should not have been touched, nor should any successful upload files have
         // appeared.
@@ -152,7 +152,7 @@
     }
 
     /**
-     * Test that ensures we can interrupt the MinidumpUploader when uploading minidumps.
+     * Test that ensures we can interrupt the MinidumpUploadJob when uploading minidumps.
      */
     @Test
     @MediumTest
@@ -175,14 +175,14 @@
                     { mIsEnabledForTests = true; }
                 };
         final CountDownLatch stopStallingLatch = new CountDownLatch(1);
-        MinidumpUploaderImpl minidumpUploader = new StallingMinidumpUploaderImpl(
+        MinidumpUploadJobImpl minidumpUploadJob = new StallingMinidumpUploadJobImpl(
                 mTestRule.getExistingCacheDir(), permManager, stopStallingLatch, successfulUpload);
 
         File firstFile = createMinidumpFileInCrashDir("123_abc.dmp0.try0");
 
         // This is run on the UI thread to avoid failing any assertOnUiThread assertions.
-        MinidumpUploadTestUtility.uploadAllMinidumpsOnUiThread(minidumpUploader,
-                new MinidumpUploader.UploadsFinishedCallback() {
+        MinidumpUploadTestUtility.uploadAllMinidumpsOnUiThread(minidumpUploadJob,
+                new MinidumpUploadJob.UploadsFinishedCallback() {
                     @Override
                     public void uploadsFinished(boolean reschedule) {
                         if (successfulUpload) {
@@ -195,11 +195,11 @@
                 // Block until job posted - otherwise the worker thread might not have been created
                 // before we try to join it.
                 true /* blockUntilJobPosted */);
-        minidumpUploader.cancelUploads();
+        minidumpUploadJob.cancelUploads();
         stopStallingLatch.countDown();
         // Wait until our job finished.
         try {
-            minidumpUploader.joinWorkerThreadForTesting();
+            minidumpUploadJob.joinWorkerThreadForTesting();
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
@@ -230,14 +230,14 @@
                     { mIsEnabledForTests = true; }
                 };
         final CountDownLatch stopStallingLatch = new CountDownLatch(1);
-        MinidumpUploaderImpl minidumpUploader =
-                new StallingMinidumpUploaderImpl(mTestRule.getExistingCacheDir(), permManager,
+        MinidumpUploadJobImpl minidumpUploadJob =
+                new StallingMinidumpUploadJobImpl(mTestRule.getExistingCacheDir(), permManager,
                         stopStallingLatch, false /* successfulUpload */);
 
         createMinidumpFileInCrashDir("123_abc.dmp0.try0");
 
-        MinidumpUploader.UploadsFinishedCallback crashingCallback =
-                new MinidumpUploader.UploadsFinishedCallback() {
+        MinidumpUploadJob.UploadsFinishedCallback crashingCallback =
+                new MinidumpUploadJob.UploadsFinishedCallback() {
                     @Override
                     public void uploadsFinished(boolean reschedule) {
                         // We don't guarantee whether uploadsFinished is called after a job has been
@@ -248,16 +248,16 @@
                 };
 
         // This is run on the UI thread to avoid failing any assertOnUiThread assertions.
-        MinidumpUploadTestUtility.uploadAllMinidumpsOnUiThread(minidumpUploader, crashingCallback);
+        MinidumpUploadTestUtility.uploadAllMinidumpsOnUiThread(minidumpUploadJob, crashingCallback);
         // Ensure we tell JobScheduler to reschedule the job.
-        Assert.assertTrue(minidumpUploader.cancelUploads());
+        Assert.assertTrue(minidumpUploadJob.cancelUploads());
         stopStallingLatch.countDown();
-        // Wait for the MinidumpUploader worker thread to finish before ending the test. This is to
+        // Wait for the MinidumpUploadJob worker thread to finish before ending the test. This is to
         // ensure the worker thread doesn't continue running after the test finishes - trying to
         // access directories or minidumps set up and deleted by the test framework.
         ThreadUtils.runOnUiThreadBlocking(() -> {
             try {
-                minidumpUploader.joinWorkerThreadForTesting();
+                minidumpUploadJob.joinWorkerThreadForTesting();
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
@@ -268,9 +268,9 @@
         MinidumpUploadCallable createCallable(File minidumpFile, File logfile);
     }
 
-    private MinidumpUploaderImpl createCallableListMinidumpUploader(
+    private MinidumpUploadJobImpl createCallableListMinidumpUploadJob(
             final List<MinidumpUploadCallableCreator> callables, final boolean userPermitted) {
-        return new TestMinidumpUploaderImpl(mTestRule.getExistingCacheDir(), null) {
+        return new TestMinidumpUploadJobImpl(mTestRule.getExistingCacheDir(), null) {
             private int mIndex;
 
             @Override
@@ -284,8 +284,8 @@
         };
     }
 
-    private static class ExpectNoUploadsMinidumpUploaderImpl extends MinidumpUploaderImpl {
-        public ExpectNoUploadsMinidumpUploaderImpl(File cacheDir) {
+    private static class ExpectNoUploadsMinidumpUploadJobImpl extends MinidumpUploadJobImpl {
+        public ExpectNoUploadsMinidumpUploadJobImpl(File cacheDir) {
             super(new TestMinidumpUploaderDelegate(
                     cacheDir, new MockCrashReportingPermissionManager() {
                         { mIsEnabledForTests = true; }
@@ -309,14 +309,14 @@
     }
 
     /**
-     * Minidump uploader implementation that stalls minidump-uploading until a given CountDownLatch
-     * counts down.
+     * Minidump upload job implementation that stalls minidump-uploading until a given
+     * CountDownLatch counts down.
      */
-    private static class StallingMinidumpUploaderImpl extends TestMinidumpUploaderImpl {
+    private static class StallingMinidumpUploadJobImpl extends TestMinidumpUploadJobImpl {
         CountDownLatch mStopStallingLatch;
         boolean mSuccessfulUpload;
 
-        public StallingMinidumpUploaderImpl(File cacheDir,
+        public StallingMinidumpUploadJobImpl(File cacheDir,
                 CrashReportingPermissionManager permissionManager, CountDownLatch stopStallingLatch,
                 boolean successfulUpload) {
             super(cacheDir, permissionManager);
diff --git a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java
index 4e44806..106a95a 100644
--- a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java
+++ b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java
@@ -21,31 +21,31 @@
     private static final long TIME_OUT_MILLIS = 3000;
 
     /**
-     * Utility method for running {@param minidumpUploader}.uploadAllMinidumps on the UI thread to
+     * Utility method for running {@param minidumpUploadJob}.uploadAllMinidumps on the UI thread to
      * avoid breaking any assertions about running on the UI thread.
      */
-    public static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
-            final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
+    public static void uploadAllMinidumpsOnUiThread(final MinidumpUploadJob minidumpUploadJob,
+            final MinidumpUploadJob.UploadsFinishedCallback uploadsFinishedCallback) {
         uploadAllMinidumpsOnUiThread(
-                minidumpUploader, uploadsFinishedCallback, false /* blockUntilJobPosted */);
+                minidumpUploadJob, uploadsFinishedCallback, false /* blockUntilJobPosted */);
     }
 
     /**
-     * Utility method for running {@param minidumpUploader}.uploadAllMinidumps on the UI thread to
+     * Utility method for running {@param minidumpUploadJob}.uploadAllMinidumps on the UI thread to
      * avoid breaking any assertions about running on the UI thread.
      * @param blockUntilJobPosted whether to block the current thread until the minidump-uploading
      *                            job has been posted to the UI thread. This can be used to avoid
      *                            some race-conditions (e.g. when waiting for variables that are
      *                            initialized in the uploadAllMinidumps call).
      */
-    public static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
-            final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback,
+    public static void uploadAllMinidumpsOnUiThread(final MinidumpUploadJob minidumpUploadJob,
+            final MinidumpUploadJob.UploadsFinishedCallback uploadsFinishedCallback,
             boolean blockUntilJobPosted) {
         final CountDownLatch jobPostedLatch = new CountDownLatch(1);
         ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                minidumpUploader.uploadAllMinidumps(uploadsFinishedCallback);
+                minidumpUploadJob.uploadAllMinidumps(uploadsFinishedCallback);
                 jobPostedLatch.countDown();
             }
         });
@@ -61,16 +61,16 @@
 
     /**
      * Utility method for uploading minidumps, and waiting for the uploads to finish.
-     * @param minidumpUploader the implementation to use to upload minidumps.
+     * @param minidumpUploadJob the implementation to use to upload minidumps.
      * @param expectReschedule value used to assert whether the uploads should be rescheduled,
      *                         e.g. when uploading succeeds we should normally not expect to
      *                         reschedule.
      */
     public static void uploadMinidumpsSync(
-            MinidumpUploader minidumpUploader, final boolean expectReschedule) {
+            MinidumpUploadJob minidumpUploadJob, final boolean expectReschedule) {
         final CountDownLatch uploadsFinishedLatch = new CountDownLatch(1);
         uploadAllMinidumpsOnUiThread(
-                minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() {
+                minidumpUploadJob, new MinidumpUploadJob.UploadsFinishedCallback() {
                     @Override
                     public void uploadsFinished(boolean reschedule) {
                         assertEquals(expectReschedule, reschedule);
diff --git a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderImpl.java b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploadJobImpl.java
similarity index 82%
rename from components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderImpl.java
rename to components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploadJobImpl.java
index f08e2036..87396af4 100644
--- a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderImpl.java
+++ b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploadJobImpl.java
@@ -9,15 +9,15 @@
 import java.io.File;
 
 /**
- * Test-implementation of MinidumpUploaderImpl.
+ * Test-implementation of MinidumpUploadJobImpl.
  */
-public class TestMinidumpUploaderImpl extends MinidumpUploaderImpl {
-    public TestMinidumpUploaderImpl(
+public class TestMinidumpUploadJobImpl extends MinidumpUploadJobImpl {
+    public TestMinidumpUploadJobImpl(
             File cacheDir, CrashReportingPermissionManager permissionManager) {
         super(new TestMinidumpUploaderDelegate(cacheDir, permissionManager));
     }
 
-    public TestMinidumpUploaderImpl(MinidumpUploaderDelegate delegate) {
+    public TestMinidumpUploadJobImpl(MinidumpUploaderDelegate delegate) {
         super(delegate);
     }
 
diff --git a/components/ntp_tiles/custom_links_manager_impl_unittest.cc b/components/ntp_tiles/custom_links_manager_impl_unittest.cc
index 504c018b..794e47e 100644
--- a/components/ntp_tiles/custom_links_manager_impl_unittest.cc
+++ b/components/ntp_tiles/custom_links_manager_impl_unittest.cc
@@ -103,9 +103,9 @@
   }
 
  protected:
+  base::ScopedTempDir scoped_temp_dir_;
   base::test::TaskEnvironment task_environment_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
-  base::ScopedTempDir scoped_temp_dir_;
   std::unique_ptr<history::HistoryService> history_service_;
   std::unique_ptr<CustomLinksManagerImpl> custom_links_;
 
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index 5bac733..ea2de4c5 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -415,95 +415,93 @@
     </if>
 
     <!-- Password Protection -->
-    <if expr="not is_android">
-      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY" desc="A one-line summary at the top of the Page Info bubble (which shows when you click the security indicator) if user has reuse their google password on current website.">
-        Your password may be compromised
+    <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY" desc="A one-line summary at the top of the Page Info bubble (which shows when you click the security indicator) if user has reuse their google password on current website.">
+      Your password may be compromised
+    </message>
+    <if expr="_google_chrome">
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
+        You could lose access to your Google Account. Chrome recommends changing your password now. You'll be asked to sign in.
       </message>
-      <if expr="_google_chrome">
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
-          You could lose access to your Google Account. Chrome recommends changing your password now. You'll be asked to sign in.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website.">
-          You just entered your password on a deceptive site. Chrome recommends changing your password now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_1_DOMAIN" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on one domain.">
-          You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph> and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on two domains.">
-          You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on three domains.">
-          You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
-          Chrome can help you protect your Google Account and change your password.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SIGNED_IN_NON_SYNC" desc="A short paragraph explaining to a non-sync user that they have reused their Google password on the current website.">
-          You just entered your password on a deceptive site. Chrome can help. To change your password and notify Google that your account may be at risk, click Protect Account.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
-          You could lose access to your organization's account or experience identity theft. Chrome recommends changing your password now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE_WITH_ORG_NAME" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
-          You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chrome recommends changing your password now.
-        </message>
-      </if>
-      <if expr="not _google_chrome">
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
-          You could lose access to your Google Account. Chromium recommends changing your password now. You'll be asked to sign in.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website.">
-          You just entered your password on a deceptive site. Chromium recommends changing your password now.
-        </message>
-         <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_1_DOMAIN" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on one domain.">
-          You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph> and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on two domains.">
-          You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on three domains.">
-          You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
-          Chromium can help you protect your Google Account and change your password.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SIGNED_IN_NON_SYNC" desc="A short paragraph explaining to a non-sync user that they have reused their Google password on the current website.">
-          You just entered your password on a deceptive site. Chromium can help. To change your password and notify Google that your account may be at risk, click Protect Account.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
-          You could lose access to your organization's account or experience identity theft. Chromium recommends changing your password now.
-        </message>
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE_WITH_ORG_NAME" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
-          You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chromium recommends changing your password now.
-        </message>
-      </if>
-
-      <if expr="use_titlecase">
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="In Title Case: The string used in the page info change password button.">
-          Change Password
-        </message>
-        <message name="IDS_PAGE_INFO_PROTECT_ACCOUNT_BUTTON" desc="In Title Case: The string used in the page info protect account button.">
-          Protect Account
-        </message>
-        <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="In Title Case: The string used in the page info ignore password warning button.">
-          Ignore
-        </message>
-      </if>
-      <if expr="not use_titlecase">
-        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="The string used in the page info change password button.">
-          Change password
-        </message>
-        <message name="IDS_PAGE_INFO_PROTECT_ACCOUNT_BUTTON" desc="The string used in the page info protect account button.">
-          Protect account
-        </message>
-        <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="The string used in the page info ignore password warning button.">
-          Ignore
-        </message>
-       </if>
-      <message name="IDS_PAGE_INFO_WHITELIST_PASSWORD_REUSE_BUTTON" desc="The string used in the page info whitelist password reuse button.">
-        Site is legitimate
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website.">
+        You just entered your password on a deceptive site. Chrome recommends changing your password now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_1_DOMAIN" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on one domain.">
+        You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph> and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on two domains.">
+        You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on three domains.">
+        You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
+        Chrome can help you protect your Google Account and change your password.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SIGNED_IN_NON_SYNC" desc="A short paragraph explaining to a non-sync user that they have reused their Google password on the current website.">
+        You just entered your password on a deceptive site. Chrome can help. To change your password and notify Google that your account may be at risk, click Protect Account.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+        You could lose access to your organization's account or experience identity theft. Chrome recommends changing your password now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE_WITH_ORG_NAME" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+        You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chrome recommends changing your password now.
       </message>
     </if>
+    <if expr="not _google_chrome">
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
+        You could lose access to your Google Account. Chromium recommends changing your password now. You'll be asked to sign in.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website.">
+        You just entered your password on a deceptive site. Chromium recommends changing your password now.
+      </message>
+       <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_1_DOMAIN" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on one domain.">
+        You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph> and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on two domains.">
+        You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on three domains.">
+        You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
+        Chromium can help you protect your Google Account and change your password.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SIGNED_IN_NON_SYNC" desc="A short paragraph explaining to a non-sync user that they have reused their Google password on the current website.">
+        You just entered your password on a deceptive site. Chromium can help. To change your password and notify Google that your account may be at risk, click Protect Account.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+        You could lose access to your organization's account or experience identity theft. Chromium recommends changing your password now.
+      </message>
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE_WITH_ORG_NAME" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+        You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chromium recommends changing your password now.
+      </message>
+    </if>
+
+    <if expr="use_titlecase">
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="In Title Case: The string used in the page info change password button.">
+        Change Password
+      </message>
+      <message name="IDS_PAGE_INFO_PROTECT_ACCOUNT_BUTTON" desc="In Title Case: The string used in the page info protect account button.">
+        Protect Account
+      </message>
+      <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="In Title Case: The string used in the page info ignore password warning button.">
+        Ignore
+      </message>
+    </if>
+    <if expr="not use_titlecase">
+      <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="The string used in the page info change password button.">
+        Change password
+      </message>
+      <message name="IDS_PAGE_INFO_PROTECT_ACCOUNT_BUTTON" desc="The string used in the page info protect account button.">
+        Protect account
+      </message>
+      <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="The string used in the page info ignore password warning button.">
+        Ignore
+      </message>
+    </if>
+    <message name="IDS_PAGE_INFO_WHITELIST_PASSWORD_REUSE_BUTTON" desc="The string used in the page info whitelist password reuse button.">
+      Site is legitimate
+    </message>
   </if>
 
      <!-- Billing -->
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 7517f940..61f51d7 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -13,15 +13,17 @@
 # TODO(crbug.com/1006430): Fix password reuse detection not fully functional on
 # Android.
 password_reuse_detection_support = !is_ios
-password_reuse_warning_support = !is_android && !is_ios
+password_reuse_warning_support = !is_ios
 password_on_focus_ping_support = !is_ios
 
 config("password_reuse_detection_config") {
   defines = []
   if (password_reuse_detection_support) {
+    # TODO(crbug.com/1036042): Rename it to PASSWORD_REUSE_DETECTION_ENABLED.
     defines += [ "SYNC_PASSWORD_REUSE_DETECTION_ENABLED" ]
   }
   if (password_reuse_warning_support) {
+    # TODO(crbug.com/1036042): Rename it to PASSWORD_REUSE_WARNING_ENABLED.
     defines += [ "SYNC_PASSWORD_REUSE_WARNING_ENABLED" ]
   }
   if (password_on_focus_ping_support) {
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn
index be3f4f1..e69d0f80e 100644
--- a/components/policy/BUILD.gn
+++ b/components/policy/BUILD.gn
@@ -381,14 +381,8 @@
   }
 
   android_resources("app_restrictions_resources") {
-    resource_dirs = []
-    generated_resource_dirs = [
-      "$policy_templates_base_dir/android",
-      _generated_resources_dir,
-    ]
-    generated_resource_files =
-        policy_templates_android_outputs +
-        [ "$_generated_resources_dir/xml-v21/app_restrictions.xml" ]
+    sources = policy_templates_android_outputs +
+              [ "$_generated_resources_dir/xml-v21/app_restrictions.xml" ]
     deps = [
       ":app_restrictions_resources_copy",
       ":policy_templates",
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 27a96fd..42167ad 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -49,6 +49,25 @@
 
 namespace {
 constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5);
+
+bool AreWindowShadowsDisabled() {
+  // When:
+  // 1) Shadows are being generated by the window server
+  // 2) The window with the shadow has a layer (all of Chrome's do)
+  // 3) Software compositing is in use (it is in most test configs, which
+  //    run in VMs)
+  // 4) There are many windows in use at once (they are when running
+  //    test in parallel)
+  // The window server seems to crash with distressing frequency. To hopefully
+  // mitigate that, disable window shadows when running on a bot.
+  // For context on this see:
+  //   https://crbug.com/899286
+  //   https://crbug.com/828031
+  //   https://crbug.com/515627, especially #63 and #67
+  static bool is_headless = getenv("CHROME_HEADLESS") != nullptr;
+  return is_headless;
+}
+
 }  // namespace
 
 // The NSView that hosts the composited CALayer drawing the UI. It fills the
@@ -440,7 +459,8 @@
                               NSWindowCollectionBehaviorParticipatesInCycle];
   }
 
-  [window_ setHasShadow:params->has_window_server_shadow];
+  [window_ setHasShadow:params->has_window_server_shadow &&
+                        !AreWindowShadowsDisabled()];
   // Don't allow dragging sheets.
   if (params->modal_type == ui::MODAL_TYPE_WINDOW)
     [window_ setMovable:NO];
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc
index 566a2d01..14a12a6 100644
--- a/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -322,7 +322,8 @@
         response ? response->verdict_type()
                  : LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+// Disabled on Android, because enterprise reporting extension is not supported.
+#if !defined(OS_ANDROID)
     MaybeReportPasswordReuseDetected(
         request->web_contents(), request->username(), request->password_type(),
         verdict == LoginReputationClientResponse::PHISHING);
diff --git a/components/safe_browsing/password_protection/password_protection_service.h b/components/safe_browsing/password_protection/password_protection_service.h
index a242cb2..4953737 100644
--- a/components/safe_browsing/password_protection/password_protection_service.h
+++ b/components/safe_browsing/password_protection/password_protection_service.h
@@ -17,6 +17,7 @@
 #include "base/scoped_observer.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "base/values.h"
+#include "build/build_config.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/history_service_observer.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
@@ -148,7 +149,11 @@
   // Shows chrome://reset-password interstitial.
   virtual void ShowInterstitial(content::WebContents* web_contens,
                                 ReusedPasswordAccountType password_type) = 0;
+#endif
 
+// The following functions are disabled on Android, because enterprise reporting
+// extension is not supported.
+#if !defined(OS_ANDROID)
   // Triggers the safeBrowsingPrivate.OnPolicySpecifiedPasswordReuseDetected.
   virtual void MaybeReportPasswordReuseDetected(
       content::WebContents* web_contents,
@@ -159,7 +164,9 @@
   // Called when a protected password change is detected. Must be called on
   // UI thread.
   virtual void ReportPasswordChanged() = 0;
+#endif
 
+#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
   virtual void UpdateSecurityState(safe_browsing::SBThreatType threat_type,
                                    ReusedPasswordAccountType password_type,
                                    content::WebContents* web_contents) = 0;
diff --git a/components/security_interstitials/content/BUILD.gn b/components/security_interstitials/content/BUILD.gn
index 91ff5c7..4f0bb733 100644
--- a/components/security_interstitials/content/BUILD.gn
+++ b/components/security_interstitials/content/BUILD.gn
@@ -5,6 +5,8 @@
 
 static_library("security_interstitial_page") {
   sources = [
+    "bad_clock_blocking_page.cc",
+    "bad_clock_blocking_page.h",
     "captive_portal_blocking_page.cc",
     "captive_portal_blocking_page.h",
     "cert_report_helper.cc",
@@ -54,6 +56,7 @@
     "//components/safe_browsing/db:hit_report",
     "//components/safe_browsing/db:util",
     "//components/security_interstitials/core:core",
+    "//components/ssl_errors",
     "//components/strings:components_strings_grit",
     "//components/url_formatter",
     "//components/user_prefs",
diff --git a/components/security_interstitials/content/DEPS b/components/security_interstitials/content/DEPS
index 5bb362d..6f960a4 100644
--- a/components/security_interstitials/content/DEPS
+++ b/components/security_interstitials/content/DEPS
@@ -6,6 +6,7 @@
   "+components/safe_browsing/common",
   "+components/safe_browsing/db",
   "+components/security_interstitials/core",
+  "+components/ssl_errors",
   "+components/user_prefs",
   "+components/variations",
   "+components/version_info",
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.cc b/components/security_interstitials/content/bad_clock_blocking_page.cc
similarity index 69%
rename from chrome/browser/ssl/bad_clock_blocking_page.cc
rename to components/security_interstitials/content/bad_clock_blocking_page.cc
index 5632fa12..d85db8b 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.cc
+++ b/components/security_interstitials/content/bad_clock_blocking_page.cc
@@ -2,18 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ssl/bad_clock_blocking_page.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
 
 #include <utility>
 
 #include "base/strings/string_number_conversions.h"
-#include "chrome/browser/interstitials/chrome_metrics_helper.h"
-#include "chrome/browser/interstitials/enterprise_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
-#include "chrome/browser/ssl/ssl_error_controller_client.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "components/security_interstitials/content/cert_report_helper.h"
+#include "components/security_interstitials/content/security_interstitial_controller_client.h"
 #include "components/security_interstitials/content/ssl_cert_reporter.h"
 #include "components/security_interstitials/core/bad_clock_ui.h"
 #include "components/security_interstitials/core/metrics_helper.h"
@@ -31,25 +27,6 @@
 using content::NavigationController;
 using content::NavigationEntry;
 
-namespace {
-
-const char kBadClockMetricsName[] = "bad_clock";
-
-std::unique_ptr<ChromeMetricsHelper> CreateBadClockMetricsHelper(
-    content::WebContents* web_contents,
-    const GURL& request_url) {
-  // Set up the metrics helper for the BadClockUI.
-  security_interstitials::MetricsHelper::ReportDetails reporting_info;
-  reporting_info.metric_prefix = kBadClockMetricsName;
-  std::unique_ptr<ChromeMetricsHelper> metrics_helper =
-      std::make_unique<ChromeMetricsHelper>(web_contents, request_url,
-                                            reporting_info);
-  metrics_helper.get()->StartRecordingCaptivePortalMetrics(false);
-  return metrics_helper;
-}
-
-}  // namespace
-
 // static
 const InterstitialPageDelegate::TypeID BadClockBlockingPage::kTypeForTesting =
     &BadClockBlockingPage::kTypeForTesting;
@@ -65,30 +42,25 @@
     const GURL& request_url,
     const base::Time& time_triggered,
     ssl_errors::ClockState clock_state,
-    std::unique_ptr<SSLCertReporter> ssl_cert_reporter)
-    : SSLBlockingPageBase(
-          web_contents,
-          CertificateErrorReport::INTERSTITIAL_CLOCK,
-          ssl_info,
-          request_url,
-          std::move(ssl_cert_reporter),
-          false /* overridable */,
-          time_triggered,
-          std::make_unique<SSLErrorControllerClient>(
-              web_contents,
-              ssl_info,
-              cert_error,
-              request_url,
-              CreateBadClockMetricsHelper(web_contents, request_url))),
+    std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
+    std::unique_ptr<
+        security_interstitials::SecurityInterstitialControllerClient>
+        controller_client)
+    : SSLBlockingPageBase(web_contents,
+                          CertificateErrorReport::INTERSTITIAL_CLOCK,
+                          ssl_info,
+                          request_url,
+                          std::move(ssl_cert_reporter),
+                          false /* overridable */,
+                          time_triggered,
+                          std::move(controller_client)),
       ssl_info_(ssl_info),
       bad_clock_ui_(new security_interstitials::BadClockUI(request_url,
                                                            cert_error,
                                                            ssl_info,
                                                            time_triggered,
                                                            clock_state,
-                                                           controller())) {
-  ChromeSecurityBlockingPageFactory::DoChromeSpecificSetup(this);
-}
+                                                           controller())) {}
 
 BadClockBlockingPage::~BadClockBlockingPage() = default;
 
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.h b/components/security_interstitials/content/bad_clock_blocking_page.h
similarity index 74%
rename from chrome/browser/ssl/bad_clock_blocking_page.h
rename to components/security_interstitials/content/bad_clock_blocking_page.h
index b9b0363..d8495a8 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.h
+++ b/components/security_interstitials/content/bad_clock_blocking_page.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_SSL_BAD_CLOCK_BLOCKING_PAGE_H_
-#define CHROME_BROWSER_SSL_BAD_CLOCK_BLOCKING_PAGE_H_
+#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_BAD_CLOCK_BLOCKING_PAGE_H_
+#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_BAD_CLOCK_BLOCKING_PAGE_H_
 
 #include <memory>
 #include <string>
@@ -35,13 +35,17 @@
   // If the blocking page isn't shown, the caller is responsible for cleaning
   // up the blocking page. Otherwise, the interstitial takes ownership when
   // shown.
-  BadClockBlockingPage(content::WebContents* web_contents,
-                       int cert_error,
-                       const net::SSLInfo& ssl_info,
-                       const GURL& request_url,
-                       const base::Time& time_triggered,
-                       ssl_errors::ClockState clock_state,
-                       std::unique_ptr<SSLCertReporter> ssl_cert_reporter);
+  BadClockBlockingPage(
+      content::WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      const base::Time& time_triggered,
+      ssl_errors::ClockState clock_state,
+      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
+      std::unique_ptr<
+          security_interstitials::SecurityInterstitialControllerClient>
+          controller_client);
 
   ~BadClockBlockingPage() override;
 
@@ -66,4 +70,4 @@
   DISALLOW_COPY_AND_ASSIGN(BadClockBlockingPage);
 };
 
-#endif  // CHROME_BROWSER_SSL_BAD_CLOCK_BLOCKING_PAGE_H_
+#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_BAD_CLOCK_BLOCKING_PAGE_H_
diff --git a/components/services/storage/public/mojom/BUILD.gn b/components/services/storage/public/mojom/BUILD.gn
index 78c6062..0ce23068 100644
--- a/components/services/storage/public/mojom/BUILD.gn
+++ b/components/services/storage/public/mojom/BUILD.gn
@@ -6,6 +6,7 @@
 
 mojom("mojom") {
   sources = [
+    "indexed_db_control.mojom",
     "local_storage_control.mojom",
     "origin_context.mojom",
     "partition.mojom",
diff --git a/components/services/storage/public/mojom/indexed_db_control.mojom b/components/services/storage/public/mojom/indexed_db_control.mojom
new file mode 100644
index 0000000..fe32bb3
--- /dev/null
+++ b/components/services/storage/public/mojom/indexed_db_control.mojom
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module storage.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+import "url/mojom/origin.mojom";
+
+// Conveys basic information about a single origin's data in IndexedDB.
+struct IndexedDBStorageUsageInfo {
+  // The origin whose metadata is represented by this structure.
+  url.mojom.Origin origin;
+
+  // The total size in bytes occupied by this origin within IndexedDB.
+  uint64 size_in_bytes;
+
+  // The last time any IndexedDB data was modified for this origin.
+  mojo_base.mojom.Time last_modified_time;
+};
+
+// Controls the state of IndexedDB within a partition. This is a privileged
+// interface and must not be brokered to untrusted clients.
+//
+// Currently this is consumed and implemented in the browser process, but the
+// implementation will eventually live in the storage service which may run
+// out-of-process.
+interface IndexedDBControl {
+  // Retrieves some basic usage information about the IndexedDB state. The
+  // returned array has one IndexedDBStorageUsageInfo per origin in the
+  // partition that has IndexedDB usage data.
+  GetUsage() => (array<IndexedDBStorageUsageInfo> info);
+};
diff --git a/components/sessions/core/live_tab_context.h b/components/sessions/core/live_tab_context.h
index 7704264d..f14affec 100644
--- a/components/sessions/core/live_tab_context.h
+++ b/components/sessions/core/live_tab_context.h
@@ -46,13 +46,13 @@
       int index) const = 0;
   // Should not be called for |group| unless GetTabGroupForTab() returned
   // |group|.
-  virtual tab_groups::TabGroupVisualData* GetVisualDataForGroup(
-      tab_groups::TabGroupId group) const = 0;
+  virtual const tab_groups::TabGroupVisualData* GetVisualDataForGroup(
+      const tab_groups::TabGroupId& group) const = 0;
   // Update |group|'s metadata. Should only be called for |group| if a tab has
   // been restored in |group| via AddRestoredTab() or ReplaceRestoredTab().
   virtual void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) = 0;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) = 0;
   virtual const gfx::Rect GetRestoredBounds() const = 0;
   virtual ui::WindowShowState GetRestoredState() const = 0;
   virtual std::string GetWorkspace() const = 0;
@@ -66,7 +66,7 @@
       int selected_navigation,
       const std::string& extension_app_id,
       base::Optional<tab_groups::TabGroupId> group,
-      const tab_groups::TabGroupVisualData group_visual_data,
+      const tab_groups::TabGroupVisualData& group_visual_data,
       bool select,
       bool pin,
       bool from_last_session,
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index d7ecf5e..3caebfcd 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -131,7 +131,7 @@
   }
 
   for (const tab_groups::TabGroupId& group : seen_groups) {
-    tab_groups::TabGroupVisualData* visual_data =
+    const tab_groups::TabGroupVisualData* visual_data =
         context->GetVisualDataForGroup(group);
     window->tab_groups.emplace(group, std::move(*visual_data));
   }
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index 0234d4e..8eb46ae 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -21,8 +21,6 @@
     "account_reconcilor_delegate.h",
     "chrome_connected_header_helper.cc",
     "chrome_connected_header_helper.h",
-    "consistency_cookie_manager_base.cc",
-    "consistency_cookie_manager_base.h",
     "cookie_reminter.cc",
     "cookie_reminter.h",
     "cookie_settings_util.cc",
@@ -31,8 +29,6 @@
     "dice_account_reconcilor_delegate.h",
     "dice_header_helper.cc",
     "dice_header_helper.h",
-    "mice_account_reconcilor_delegate.cc",
-    "mice_account_reconcilor_delegate.h",
     "mirror_account_reconcilor_delegate.cc",
     "mirror_account_reconcilor_delegate.h",
     "signin_error_controller.cc",
@@ -93,14 +89,6 @@
     ]
   }
 
-  if (is_android) {
-    sources += [
-      "consistency_cookie_manager_android.cc",
-      "consistency_cookie_manager_android.h",
-    ]
-    deps += [ "android:jni_headers" ]
-  }
-
   if (!enable_dice_support) {
     sources -= [
       "dice_account_reconcilor_delegate.cc",
@@ -117,7 +105,6 @@
     "account_investigator_unittest.cc",
     "account_reconcilor_unittest.cc",
     "dice_account_reconcilor_delegate_unittest.cc",
-    "mice_account_reconcilor_delegate_unittest.cc",
     "signin_error_controller_unittest.cc",
     "signin_header_helper_unittest.cc",
     "signin_investigator_unittest.cc",
@@ -154,10 +141,6 @@
     ]
   }
 
-  if (is_android) {
-    sources += [ "consistency_cookie_manager_unittest.cc" ]
-  }
-
   if (!enable_dice_support) {
     sources -= [ "dice_account_reconcilor_delegate_unittest.cc" ]
   }
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index ff5b0e6..95bdfb3 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -21,7 +21,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/core/browser/consistency_cookie_manager_base.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/base/signin_metrics.h"
@@ -33,10 +32,6 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
-#if defined(OS_ANDROID)
-#include "components/signin/core/browser/consistency_cookie_manager_android.h"
-#endif
-
 using signin::AccountReconcilorDelegate;
 using signin_metrics::AccountReconcilorState;
 
@@ -282,12 +277,6 @@
   }
 }
 
-void AccountReconcilor::SetConsistencyCookieManager(
-    std::unique_ptr<signin::ConsistencyCookieManagerBase>
-        consistency_cookie_manager) {
-  consistency_cookie_manager_ = std::move(consistency_cookie_manager);
-}
-
 void AccountReconcilor::EnableReconcile() {
   SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED);
   RegisterWithAllDependencies();
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h
index df65ed4..0d7c3e6c 100644
--- a/components/signin/core/browser/account_reconcilor.h
+++ b/components/signin/core/browser/account_reconcilor.h
@@ -30,7 +30,6 @@
 
 namespace signin {
 class AccountReconcilorDelegate;
-class ConsistencyCookieManagerBase;
 enum class SetAccountsInCookieResult;
 }
 
@@ -99,10 +98,6 @@
   // construction.
   void Initialize(bool start_reconcile_if_tokens_available);
 
-  void SetConsistencyCookieManager(
-      std::unique_ptr<signin::ConsistencyCookieManagerBase>
-          consistency_cookie_manager);
-
   // Enables and disables the reconciliation.
   void EnableReconcile();
   void DisableReconcile(bool logout_all_gaia_accounts);
@@ -373,9 +368,6 @@
 
   signin_metrics::AccountReconcilorState state_;
 
-  std::unique_ptr<signin::ConsistencyCookieManagerBase>
-      consistency_cookie_manager_;
-
   base::WeakPtrFactory<AccountReconcilor> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 722e573..91c6e5b8 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -21,7 +21,6 @@
 #include "build/build_config.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/core/browser/mice_account_reconcilor_delegate.h"
 #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/list_accounts_test_utils.h"
@@ -144,10 +143,6 @@
       bool dice_migration_completed) {
     switch (account_consistency) {
       case signin::AccountConsistencyMethod::kMirror:
-#if defined(OS_ANDROID)
-        if (base::FeatureList::IsEnabled(signin::kMiceFeature))
-          return std::make_unique<signin::MiceAccountReconcilorDelegate>();
-#endif
         return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
             identity_manager);
       case signin::AccountConsistencyMethod::kDisabled:
@@ -292,21 +287,6 @@
   DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest);
 };
 
-#if defined(OS_ANDROID)
-// Same as AccountReconcilorTest, with Mice enabled.
-class AccountReconcilorMiceTest : public AccountReconcilorTest {
- public:
-  AccountReconcilorMiceTest() {
-    SetAccountConsistency(signin::AccountConsistencyMethod::kMirror);
-    scoped_feature_list_.InitAndEnableFeature(signin::kMiceFeature);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  DISALLOW_COPY_AND_ASSIGN(AccountReconcilorMiceTest);
-};
-#endif
-
 class AccountReconcilorMirrorTest : public AccountReconcilorTest {
  public:
   AccountReconcilorMirrorTest() {
@@ -1872,193 +1852,6 @@
     ::testing::ValuesIn(GenerateTestCasesFromParams(kActiveDirectoryParams)));
 #endif  // defined(OS_CHROMEOS)
 
-#if defined(OS_ANDROID)
-// clang-format off
-const std::vector<AccountReconcilorTestTableParam> kMiceParams = {
-// This table encodes the initial state and expectations of a reconcile.
-// See kDiceParams for documentation of the syntax.
-// -------------------------------------------------------------------------
-// Tokens | Cookies | First Run            | Gaia calls | Tokens after | Cookies after
-// -------------------------------------------------------------------------
-{  "A",     "A",    IsFirstReconcile::kBoth, "",          "A",           "A"},
-{  "A",     "B",    IsFirstReconcile::kBoth, "U",         "A",           "A"},
-{  "A",     "",     IsFirstReconcile::kBoth, "U",         "A",           "A"},
-{  "A",     "xA",   IsFirstReconcile::kBoth, "U",         "A",           "A"},
-{  "A",     "AxB",  IsFirstReconcile::kBoth, "U",         "A",           "A"},
-{  "xA",    "A",    IsFirstReconcile::kBoth, "X",         "xA",          ""},
-{  "xA",    "xA",   IsFirstReconcile::kBoth, "",          "xA",          "xA"},
-{  "xA",    "xB",   IsFirstReconcile::kBoth, "X",         "xA",          ""},
-{  "xA",    "",     IsFirstReconcile::kBoth, "",          "xA",          ""},
-{  "",      "A",    IsFirstReconcile::kBoth, "X",         "",            ""},
-{  "",      "xA",   IsFirstReconcile::kBoth, "X",         "",            ""},
-};
-// clang-format on
-
-// Parameterized version of AccountReconcilorTest that tests Mice implementation
-// with Multilogin endpoint.
-class AccountReconcilorTestMiceMultilogin : public AccountReconcilorTestTable {
- public:
-  AccountReconcilorTestMiceMultilogin() = default;
-
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestMiceMultilogin);
-};
-
-// Checks one row of the kMiceParams table above.
-TEST_P(AccountReconcilorTestMiceMultilogin, TableRowTest) {
-  // Enable Mirror.
-  SetAccountConsistency(signin::AccountConsistencyMethod::kMirror);
-  scoped_feature_list_.InitAndEnableFeature(signin::kMiceFeature);
-
-  // Setup cookies.
-  std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
-  ConfigureCookieManagerService(cookies);
-
-  // Setup tokens. This triggers listing cookies so we need to setup cookies
-  // before that.
-  SetupTokens(GetParam().tokens);
-
-  // Call list accounts now so that the next call completes synchronously.
-  identity_test_env()->identity_manager()->GetAccountsInCookieJar();
-  base::RunLoop().RunUntilIdle();
-
-  // Setup expectations.
-  testing::InSequence mock_sequence;
-  bool logout_action = false;
-  for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
-    if (GetParam().gaia_api_calls[i] == 'X') {
-      logout_action = true;
-      EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-          .Times(1);
-      cookies.clear();
-      continue;
-    }
-    if (GetParam().gaia_api_calls[i] == 'U') {
-      std::vector<CoreAccountId> accounts_to_send;
-      for (int i = 0; GetParam().cookies_after_reconcile[i] != '\0'; ++i) {
-        char cookie = GetParam().cookies_after_reconcile[i];
-        std::string account_to_send = GaiaIdForAccountKey(cookie);
-        accounts_to_send.push_back(PickAccountIdForAccount(
-            account_to_send,
-            accounts_[GetParam().cookies_after_reconcile[i]].email));
-      }
-      const signin::MultiloginParameters params(
-          gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
-          accounts_to_send);
-      EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params))
-          .Times(1);
-    }
-  }
-  if (!logout_action) {
-    EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-        .Times(0);
-  }
-
-  // Reconcile.
-  AccountReconcilor* reconcilor = GetMockReconcilor();
-  ASSERT_TRUE(reconcilor);
-  ASSERT_TRUE(reconcilor->first_execution_);
-  reconcilor->first_execution_ =
-      GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
-  reconcilor->StartReconcile();
-
-  SimulateSetAccountsInCookieCompleted(
-      reconcilor, signin::SetAccountsInCookieResult::kSuccess);
-
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
-  VerifyCurrentTokens(ParseTokenString(GetParam().tokens_after_reconcile));
-
-  testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
-
-  // Another reconcile is sometimes triggered if Chrome accounts have
-  // changed. Allow it to finish.
-  EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
-      .WillRepeatedly(testing::Return());
-  EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-      .WillRepeatedly(testing::Return());
-  ConfigureCookieManagerService({});
-  base::RunLoop().RunUntilIdle();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    MiceTableMultilogin,
-    AccountReconcilorTestMiceMultilogin,
-    ::testing::ValuesIn(GenerateTestCasesFromParams(kMiceParams)));
-
-// Checks that the reconcilor state does:
-// RUNNING -> SCHEDULED -> RUNNING -> OK.
-TEST_F(AccountReconcilorMiceTest, AccountReconcilorStateScheduled) {
-  class TestAccountReconcilorObserver
-      : public testing::StrictMock<AccountReconcilor::Observer> {
-   public:
-    MOCK_METHOD1(OnStateChanged, void(AccountReconcilorState state));
-  };
-
-  AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
-  signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
-
-  EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_));
-
-  // The reconcilor should run twice without going to the OK state in between.
-  // OK only happens at the end.
-  TestAccountReconcilorObserver observer;
-  testing::InSequence mock_sequence;
-  EXPECT_CALL(observer, OnStateChanged(
-                            AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING))
-      .Times(1);
-  EXPECT_CALL(
-      observer,
-      OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED))
-      .Times(1);
-  EXPECT_CALL(observer, OnStateChanged(
-                            AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING))
-      .Times(1);
-  EXPECT_CALL(observer,
-              OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_OK))
-      .Times(1);
-
-  AccountReconcilor* reconcilor = GetMockReconcilor();
-  ASSERT_TRUE(reconcilor);
-  ScopedObserver<AccountReconcilor, AccountReconcilor::Observer>
-      scoped_observer(&observer);
-  scoped_observer.Add(reconcilor);
-
-  // Reconcile was scheduled when the account was added.
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED,
-            reconcilor->GetState());
-
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  reconcilor->StartReconcile();
-  ASSERT_TRUE(reconcilor->is_reconcile_started_);
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING,
-            reconcilor->GetState());
-  base::RunLoop().RunUntilIdle();
-
-  // The reconcilor started a request to add the account to the cookie, and is
-  // waiting for the response.
-
-  // Change the token while the reconcilor is running, to trigger another
-  // reconcile after the current one.
-  identity_test_env()->SetInvalidRefreshTokenForAccount(
-      account_info.account_id);
-
-  // Unblock the first reconcile.
-  SimulateSetAccountsInCookieCompleted(
-      reconcilor, signin::SetAccountsInCookieResult::kSuccess);
-  // Wait until the first reconcile finishes, and a second reconcile is done.
-  // The second reconcile will be a no-op.
-  base::RunLoop().RunUntilIdle();
-
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_OK,
-            reconcilor->GetState());
-}
-#endif  // defined(OS_ANDROID)
-
 // Tests that reconcile cannot start before the tokens are loaded, and is
 // automatically started when tokens are loaded.
 TEST_F(AccountReconcilorMirrorTest, TokensNotLoaded) {
@@ -2738,113 +2531,6 @@
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
 }
 
-// Checks that the reconcilor state does:
-// RUNNING -> SCHEDULED -> RUNNING -> OK.
-// This test is similar to
-// AccountReconcilorMiceTest.AccountReconctiorStateScheduled, but uses the
-// MergeSession endpoint. It also uses multiple accounts, because Mirror would
-// stop when the first account is in error.
-TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
-  class TestAccountReconcilorObserver
-      : public testing::StrictMock<AccountReconcilor::Observer> {
-   public:
-    MOCK_METHOD1(OnStateChanged, void(AccountReconcilorState state));
-  };
-
-  signin::AccountConsistencyMethod account_consistency = GetParam();
-  SetAccountConsistency(account_consistency);
-  AccountInfo account_info1 = ConnectProfileToAccount("user@gmail.com");
-  AccountInfo account_info2 =
-      identity_test_env()->MakeAccountAvailable("other@gmail.com");
-  const CoreAccountId account_id1 = account_info1.account_id;
-  const CoreAccountId account_id2 = account_info2.account_id;
-  signin::SetListAccountsResponseOneAccount(
-      account_info1.email, account_info1.gaia, &test_url_loader_factory_);
-
-  AccountReconcilor* reconcilor = GetMockReconcilor();
-  ASSERT_TRUE(reconcilor);
-
-  if (!reconcilor->IsMultiloginEndpointEnabled()) {
-    EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
-  } else {
-    switch (account_consistency) {
-      case signin::AccountConsistencyMethod::kMirror: {
-        signin::MultiloginParameters params(
-            gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
-            {account_id1, account_id2});
-        EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
-        break;
-      }
-      case signin::AccountConsistencyMethod::kDice: {
-        signin::MultiloginParameters params(
-            gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
-            {account_id2, account_id1});
-        EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
-        break;
-      }
-      case signin::AccountConsistencyMethod::kDisabled:
-        NOTREACHED();
-        break;
-    }
-  }
-
-  // The reconcilor should run twice without going to the OK state in between.
-  // OK only happens at the end.
-  TestAccountReconcilorObserver observer;
-  testing::InSequence mock_sequence;
-  EXPECT_CALL(observer, OnStateChanged(
-                            AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING))
-      .Times(1);
-  EXPECT_CALL(
-      observer,
-      OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED))
-      .Times(1);
-  EXPECT_CALL(observer, OnStateChanged(
-                            AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING))
-      .Times(1);
-  EXPECT_CALL(observer,
-              OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_OK))
-      .Times(1);
-
-  ScopedObserver<AccountReconcilor, AccountReconcilor::Observer>
-      scoped_observer(&observer);
-  scoped_observer.Add(reconcilor);
-
-  // Reconcile was scheduled when the account was added.
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED,
-            reconcilor->GetState());
-
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  reconcilor->StartReconcile();
-  ASSERT_TRUE(reconcilor->is_reconcile_started_);
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING,
-            reconcilor->GetState());
-  base::RunLoop().RunUntilIdle();
-
-  // The reconcilor started a request to add the account to the cookie, and is
-  // waiting for the response.
-
-  // Change the token while the reconcilor is running, to trigger another
-  // reconcile after the current one.
-  identity_test_env()->RemoveRefreshTokenForAccount(account_id2);
-
-  if (!reconcilor->IsMultiloginEndpointEnabled()) {
-    SimulateAddAccountToCookieCompleted(
-        reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
-  } else {
-    SimulateSetAccountsInCookieCompleted(
-        reconcilor, signin::SetAccountsInCookieResult::kSuccess);
-  }
-
-  // Wait until the first reconcile finishes, and a second reconcile is done.
-  // The second reconcile will be a no-op.
-  base::RunLoop().RunUntilIdle();
-
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  EXPECT_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_OK,
-            reconcilor->GetState());
-}
-
 TEST_F(AccountReconcilorMirrorTest,
        AddAccountToCookieCompletedWithBogusAccount) {
   AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn
index 6aeade69..8f58aad 100644
--- a/components/signin/core/browser/android/BUILD.gn
+++ b/components/signin/core/browser/android/BUILD.gn
@@ -9,7 +9,6 @@
     "java/src/org/chromium/components/signin/AccountManagerFacade.java",
     "java/src/org/chromium/components/signin/AccountTrackerService.java",
     "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
-    "java/src/org/chromium/components/signin/ConsistencyCookieManager.java",
   ]
 }
 
@@ -38,13 +37,11 @@
     "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
     "java/src/org/chromium/components/signin/ChildAccountStatus.java",
     "java/src/org/chromium/components/signin/ChromeSigninController.java",
-    "java/src/org/chromium/components/signin/ConsistencyCookieManager.java",
     "java/src/org/chromium/components/signin/GmsAvailabilityException.java",
     "java/src/org/chromium/components/signin/GmsJustUpdatedException.java",
     "java/src/org/chromium/components/signin/MutableObservableValue.java",
     "java/src/org/chromium/components/signin/ObservableValue.java",
     "java/src/org/chromium/components/signin/ProfileDataSource.java",
-    "java/src/org/chromium/components/signin/SigninActivityMonitor.java",
     "java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java",
     "java/src/org/chromium/components/signin/util/PatternMatcher.java",
   ]
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java
deleted file mode 100644
index 44fa6be..0000000
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java
+++ /dev/null
@@ -1,97 +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.components.signin;
-
-import androidx.annotation.MainThread;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-
-/**
- * Created by native code to get status of {@link AccountManagerFacade#isUpdatePending()} and
- * notifications when it changes.
- */
-public class ConsistencyCookieManager
-        implements ObservableValue.Observer, AccountTrackerService.OnSystemAccountsSeededListener {
-    private final long mNativeConsistencyCookieManager;
-    private final AccountTrackerService mAccountTrackerService;
-    private final AccountManagerFacade mAccountManagerFacade;
-    private final SigninActivityMonitor mSigninActivityMonitor;
-    private boolean mIsUpdatePending;
-
-    private ConsistencyCookieManager(
-            long nativeConsistencyCookieManager, AccountTrackerService accountTrackerService) {
-        ThreadUtils.assertOnUiThread();
-        mAccountTrackerService = accountTrackerService;
-        mNativeConsistencyCookieManager = nativeConsistencyCookieManager;
-        mAccountManagerFacade = AccountManagerFacade.get();
-        mSigninActivityMonitor = SigninActivityMonitor.get();
-
-        // For now, this class relies on the order of notifications sent by AccountManagerFacade and
-        // AccountTrackerService. Whenever the account list changes, this class will get
-        // notification from AccountManagerFacade.isUpdatePending(). This will change
-        // mIsUpdatePending to true. By the time AccountManagerFacade finishes updating account list
-        // and sets AccountManagerFacade.isUpdatePending() to false, AccountTrackerService should
-        // have already invalidate account seed status, so mIsUpdatePending will stay false until
-        // accounts are seeded to the native AccountTrackerService.
-        // TODO(https://crbug.com/831257): Simplify this after seeding is reimplemented.
-        mAccountTrackerService.addSystemAccountsSeededListener(this);
-        mAccountManagerFacade.isUpdatePending().addObserver(this);
-        mSigninActivityMonitor.hasOngoingActivity().addObserver(this);
-
-        mIsUpdatePending = calculateIsUpdatePending();
-    }
-
-    @Override
-    public void onSystemAccountsSeedingComplete() {
-        onValueChanged();
-    }
-
-    @Override
-    public void onValueChanged() {
-        boolean state = calculateIsUpdatePending();
-
-        if (mIsUpdatePending == state) return;
-        mIsUpdatePending = state;
-        ConsistencyCookieManagerJni.get().onIsUpdatePendingChanged(mNativeConsistencyCookieManager);
-    }
-
-    private boolean calculateIsUpdatePending() {
-        return mAccountManagerFacade.isUpdatePending().get()
-                || mSigninActivityMonitor.hasOngoingActivity().get()
-                || !mAccountTrackerService.areSystemAccountsSeeded();
-    }
-
-    @CalledByNative
-    @MainThread
-    private static ConsistencyCookieManager create(
-            long nativeConsistencyCookieManager, AccountTrackerService accountTrackerService) {
-        return new ConsistencyCookieManager(nativeConsistencyCookieManager, accountTrackerService);
-    }
-
-    @CalledByNative
-    @MainThread
-    private void destroy() {
-        ThreadUtils.assertOnUiThread();
-        mAccountTrackerService.removeSystemAccountsSeededListener(this);
-        mSigninActivityMonitor.hasOngoingActivity().removeObserver(this);
-        mAccountManagerFacade.isUpdatePending().removeObserver(this);
-    }
-
-    @CalledByNative
-    @MainThread
-    private boolean getIsUpdatePending() {
-        ThreadUtils.assertOnUiThread();
-        return mIsUpdatePending;
-    }
-
-    @JNINamespace("signin")
-    @NativeMethods
-    interface Natives {
-        void onIsUpdatePendingChanged(long nativeConsistencyCookieManagerAndroid);
-    }
-}
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SigninActivityMonitor.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SigninActivityMonitor.java
deleted file mode 100644
index 7fe5018..0000000
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SigninActivityMonitor.java
+++ /dev/null
@@ -1,68 +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.components.signin;
-
-import android.annotation.SuppressLint;
-
-import androidx.annotation.MainThread;
-
-import org.chromium.base.ThreadUtils;
-
-/**
- * Monitors external activities started from sign-in flows (for example, activity to add an account
- * to the device). Activities have to be launched using {@link #startSigninActivity}.
- */
-public class SigninActivityMonitor {
-    @SuppressLint("StaticFieldLeak")
-    private static SigninActivityMonitor sInstance;
-
-    private int mActivityCounter;
-    private MutableObservableValue<Boolean> mHasOngoingActivity =
-            new MutableObservableValue<>(false);
-
-    private SigninActivityMonitor() {}
-
-    /**
-     * Returns a singleton instance of the SigninActivityMonitor.
-     */
-    @MainThread
-    public static SigninActivityMonitor get() {
-        ThreadUtils.assertOnUiThread();
-        if (sInstance == null) {
-            sInstance = new SigninActivityMonitor();
-        }
-        return sInstance;
-    }
-
-    /**
-     * Returns whether there are any ongoing sign-in activities.
-     */
-    public ObservableValue<Boolean> hasOngoingActivity() {
-        return mHasOngoingActivity;
-    }
-
-    // TODO(https://crbug.com/953765): Make this private.
-    /**
-     * Should be invoked when a signin activity is started.
-     */
-    public void activityStarted() {
-        assert mActivityCounter >= 0;
-
-        ++mActivityCounter;
-        if (mActivityCounter == 1) mHasOngoingActivity.set(true);
-    }
-
-    // TODO(https://crbug.com/953765): Make this private.
-    /**
-     * Should be invoked when a signin activity is finished. There should be a strict parity between
-     * {@link #activityStarted()} and {@link #activityFinished()} calls.
-     */
-    public void activityFinished() {
-        assert mActivityCounter > 0;
-
-        --mActivityCounter;
-        if (mActivityCounter == 0) mHasOngoingActivity.set(false);
-    }
-}
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index ec98e97..c40f6c2 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -169,12 +169,6 @@
     const GURL& url,
     const std::string& gaia_id,
     int profile_mode_mask) {
-#if defined(OS_ANDROID)
-  bool is_mice_enabled = base::FeatureList::IsEnabled(kMiceFeature);
-#else
-  bool is_mice_enabled = false;
-#endif
-
 // If we are on mobile or desktop, an empty |account_id| corresponds to the user
 // not signed into Sync. Do not enforce account consistency, unless Mice is
 // enabled on Android.
@@ -183,7 +177,7 @@
 // filtered upstream and we want to enforce account consistency in Public
 // Sessions and Active Directory logins.
 #if !defined(OS_CHROMEOS)
-  if (gaia_id.empty() && !is_mice_enabled)
+  if (gaia_id.empty())
     return std::string();
 #endif  // !defined(OS_CHROMEOS)
 
@@ -201,9 +195,8 @@
       account_consistency_ == AccountConsistencyMethod::kMirror;
   parts.push_back(base::StringPrintf("%s=%s", kEnableAccountConsistencyAttrName,
                                      is_mirror_enabled ? "true" : "false"));
-  parts.push_back(base::StringPrintf("%s=%s",
-                                     kConsistencyEnabledByDefaultAttrName,
-                                     is_mice_enabled ? "true" : "false"));
+  parts.push_back(base::StringPrintf(
+      "%s=%s", kConsistencyEnabledByDefaultAttrName, "false"));
 
   return base::JoinString(parts, is_header_request ? "," : ":");
 }
diff --git a/components/signin/core/browser/consistency_cookie_manager_android.cc b/components/signin/core/browser/consistency_cookie_manager_android.cc
deleted file mode 100644
index cd1f0cc..0000000
--- a/components/signin/core/browser/consistency_cookie_manager_android.cc
+++ /dev/null
@@ -1,50 +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 "components/signin/core/browser/consistency_cookie_manager_android.h"
-
-#include "components/signin/core/browser/android/jni_headers/ConsistencyCookieManager_jni.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
-
-namespace signin {
-
-ConsistencyCookieManagerAndroid::ConsistencyCookieManagerAndroid(
-    IdentityManager* identity_manager,
-    SigninClient* signin_client,
-    AccountReconcilor* reconcilor)
-    : ConsistencyCookieManagerBase(signin_client, reconcilor) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  base::android::ScopedJavaLocalRef<jobject> java_ref =
-      Java_ConsistencyCookieManager_create(
-          env, reinterpret_cast<intptr_t>(this),
-          identity_manager->LegacyGetAccountTrackerServiceJavaObject());
-  java_ref_.Reset(env, java_ref.obj());
-  is_update_pending_in_java_ =
-      Java_ConsistencyCookieManager_getIsUpdatePending(env, java_ref_);
-
-  UpdateCookie();
-}
-
-ConsistencyCookieManagerAndroid::~ConsistencyCookieManagerAndroid() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  Java_ConsistencyCookieManager_destroy(env, java_ref_);
-}
-
-void ConsistencyCookieManagerAndroid::OnIsUpdatePendingChanged(JNIEnv* env) {
-  bool is_update_pending_in_java =
-      Java_ConsistencyCookieManager_getIsUpdatePending(env, java_ref_);
-  if (is_update_pending_in_java == is_update_pending_in_java_)
-    return;
-  is_update_pending_in_java_ = is_update_pending_in_java;
-  UpdateCookie();
-}
-
-std::string ConsistencyCookieManagerAndroid::CalculateCookieValue() {
-  if (is_update_pending_in_java_) {
-    return kStateUpdating;
-  }
-  return ConsistencyCookieManagerBase::CalculateCookieValue();
-}
-
-}  // namespace signin
diff --git a/components/signin/core/browser/consistency_cookie_manager_android.h b/components/signin/core/browser/consistency_cookie_manager_android.h
deleted file mode 100644
index 6fa0f2e..0000000
--- a/components/signin/core/browser/consistency_cookie_manager_android.h
+++ /dev/null
@@ -1,42 +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 COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_ANDROID_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_ANDROID_H_
-
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "components/signin/core/browser/consistency_cookie_manager_base.h"
-
-class SigninClient;
-
-namespace signin {
-
-class IdentityManager;
-
-// ConsistencyCookieManagerAndroid subclasses ConsistencyCookieManagerBase to
-// watch whether there are pending updates to the account list on the Java side.
-class ConsistencyCookieManagerAndroid : public ConsistencyCookieManagerBase {
- public:
-  ConsistencyCookieManagerAndroid(IdentityManager* identity_manager,
-                                  SigninClient* signin_client,
-                                  AccountReconcilor* reconcilor);
-
-  ~ConsistencyCookieManagerAndroid() override;
-
-  void OnIsUpdatePendingChanged(JNIEnv* env);
-
- protected:
-  std::string CalculateCookieValue() override;
-
- private:
-  bool is_update_pending_in_java_ = false;
-  base::android::ScopedJavaGlobalRef<jobject> java_ref_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConsistencyCookieManagerAndroid);
-};
-
-}  // namespace signin
-
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_ANDROID_H_
diff --git a/components/signin/core/browser/consistency_cookie_manager_base.cc b/components/signin/core/browser/consistency_cookie_manager_base.cc
deleted file mode 100644
index 92dee2a0..0000000
--- a/components/signin/core/browser/consistency_cookie_manager_base.cc
+++ /dev/null
@@ -1,83 +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 "components/signin/core/browser/consistency_cookie_manager_base.h"
-
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "components/signin/public/base/signin_client.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/cookies/canonical_cookie.h"
-#include "net/cookies/cookie_options.h"
-#include "services/network/public/mojom/cookie_manager.mojom.h"
-#include "url/gurl.h"
-
-namespace signin {
-
-const char kCookieName[] = "CHROME_ID_CONSISTENCY_STATE";
-const char ConsistencyCookieManagerBase::kStateConsistent[] = "Consistent";
-const char ConsistencyCookieManagerBase::kStateInconsistent[] = "Inconsistent";
-const char ConsistencyCookieManagerBase::kStateUpdating[] = "Updating";
-
-ConsistencyCookieManagerBase::ConsistencyCookieManagerBase(
-    SigninClient* signin_client,
-    AccountReconcilor* reconcilor)
-    : account_reconcilor_state_(reconcilor->GetState()),
-      signin_client_(signin_client),
-      account_reconcilor_observer_(this) {
-  DCHECK(signin_client_);
-  DCHECK(reconcilor);
-
-  account_reconcilor_observer_.Add(reconcilor);
-}
-
-ConsistencyCookieManagerBase::~ConsistencyCookieManagerBase() = default;
-
-void ConsistencyCookieManagerBase::OnStateChanged(
-    signin_metrics::AccountReconcilorState state) {
-  if (state == account_reconcilor_state_)
-    return;
-  account_reconcilor_state_ = state;
-  UpdateCookie();
-}
-
-std::string ConsistencyCookieManagerBase::CalculateCookieValue() {
-  switch (account_reconcilor_state_) {
-    case signin_metrics::ACCOUNT_RECONCILOR_OK:
-      return kStateConsistent;
-    case signin_metrics::ACCOUNT_RECONCILOR_RUNNING:
-    case signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED:
-      return kStateUpdating;
-    case signin_metrics::ACCOUNT_RECONCILOR_ERROR:
-      return kStateInconsistent;
-    case signin_metrics::ACCOUNT_RECONCILOR_HISTOGRAM_COUNT:
-      NOTREACHED();
-      return {};
-  }
-}
-
-void ConsistencyCookieManagerBase::UpdateCookie() {
-  std::string cookie_value = CalculateCookieValue();
-  DCHECK(!cookie_value.empty());
-
-  // Update the cookie with the new value.
-  network::mojom::CookieManager* cookie_manager =
-      signin_client_->GetCookieManager();
-  base::Time now = base::Time::Now();
-  base::Time expiry = now + base::TimeDelta::FromDays(2 * 365);  // Two years.
-  net::CanonicalCookie cookie(
-      kCookieName, cookie_value, GaiaUrls::GetInstance()->gaia_url().host(),
-      /*path=*/"/", /*creation=*/now, /*expiration=*/expiry,
-      /*last_access=*/now, /*secure=*/true, /*httponly=*/false,
-      net::CookieSameSite::LAX_MODE, net::COOKIE_PRIORITY_DEFAULT);
-  net::CookieOptions cookie_options;
-  // Permit to set SameSite cookies.
-  cookie_options.set_same_site_cookie_context(
-      net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
-  cookie_manager->SetCanonicalCookie(
-      cookie, "https", cookie_options,
-      network::mojom::CookieManager::SetCanonicalCookieCallback());
-}
-
-}  // namespace signin
diff --git a/components/signin/core/browser/consistency_cookie_manager_base.h b/components/signin/core/browser/consistency_cookie_manager_base.h
deleted file mode 100644
index 7c1d551..0000000
--- a/components/signin/core/browser/consistency_cookie_manager_base.h
+++ /dev/null
@@ -1,61 +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 COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_BASE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_BASE_H_
-
-#include "base/macros.h"
-#include "base/scoped_observer.h"
-#include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/public/base/signin_metrics.h"
-
-class SigninClient;
-
-namespace signin {
-
-// The ConsistencyCookieManagerBase checks if:
-// - the account reconcilor is running
-// - the accounts on the device are updating
-// - the user has started to interact with device account settings (from Chrome)
-// If one of these conditions is true, then this object sets a cookie on Gaia
-// with a "Updating" value.
-//
-// Otherwise the value of the cookie is "Consistent" if the accounts are
-// consistent (web accounts match device accounts) or "Inconsistent".
-//
-// Subclasses have to call UpdateCookie() at the end of the constructor.
-class ConsistencyCookieManagerBase : public AccountReconcilor::Observer {
- public:
-  ~ConsistencyCookieManagerBase() override;
-
- protected:
-  static const char kStateConsistent[];
-  static const char kStateInconsistent[];
-  static const char kStateUpdating[];
-
-  ConsistencyCookieManagerBase(SigninClient* signin_client,
-                               AccountReconcilor* reconcilor);
-
-  // Calculates the cookie value solely based on the reconcilor state.
-  virtual std::string CalculateCookieValue();
-
-  // Gets the new value using CalculateCookieValue and sets the cookie.
-  void UpdateCookie();
-
- private:
-  // AccountReconcilor::Observer:
-  void OnStateChanged(signin_metrics::AccountReconcilorState state) override;
-
-  signin_metrics::AccountReconcilorState account_reconcilor_state_ =
-      signin_metrics::ACCOUNT_RECONCILOR_OK;
-  SigninClient* signin_client_ = nullptr;
-  ScopedObserver<AccountReconcilor, AccountReconcilor::Observer>
-      account_reconcilor_observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConsistencyCookieManagerBase);
-};
-
-}  // namespace signin
-
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_CONSISTENCY_COOKIE_MANAGER_BASE_H_
diff --git a/components/signin/core/browser/consistency_cookie_manager_unittest.cc b/components/signin/core/browser/consistency_cookie_manager_unittest.cc
deleted file mode 100644
index b0cbd10..0000000
--- a/components/signin/core/browser/consistency_cookie_manager_unittest.cc
+++ /dev/null
@@ -1,132 +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 "components/signin/core/browser/consistency_cookie_manager_base.h"
-
-#include <memory>
-#include <string>
-
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/core/browser/account_reconcilor_delegate.h"
-#include "components/signin/public/base/account_consistency_method.h"
-#include "components/signin/public/base/test_signin_client.h"
-#include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "services/network/test/test_cookie_manager.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace signin {
-namespace {
-
-// GMock matcher that checks that the consistency cookie has the expected value.
-MATCHER_P(CookieHasValueMatcher, value, "") {
-  net::CookieOptions cookie_options;
-  cookie_options.set_same_site_cookie_context(
-      net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
-  return arg.Name() == "CHROME_ID_CONSISTENCY_STATE" && arg.Value() == value &&
-         arg.IncludeForRequestURL(GaiaUrls::GetInstance()->gaia_url(),
-                                  cookie_options)
-             .IsInclude();
-}
-
-MATCHER(SetPermittedInContext, "") {
-  const net::CanonicalCookie& cookie = testing::get<0>(arg);
-  const net::CookieOptions& cookie_options = testing::get<1>(arg);
-  return cookie.IsSetPermittedInContext(cookie_options).IsInclude();
-}
-
-class MockCookieManager
-    : public testing::StrictMock<network::TestCookieManager> {
- public:
-  // Adds a GMock expectation that the consistency cookie will be set with the
-  // specified value.
-  void ExpectSetCookieCall(const std::string& value) {
-    EXPECT_CALL(*this, SetCanonicalCookie(CookieHasValueMatcher(value), "https",
-                                          testing::_, testing::_))
-        .With(testing::Args<0, 2>(SetPermittedInContext()));
-  }
-
-  MOCK_METHOD4(
-      SetCanonicalCookie,
-      void(const net::CanonicalCookie& cookie,
-           const std::string& source_scheme,
-           const net::CookieOptions& cookie_options,
-           network::mojom::CookieManager::SetCanonicalCookieCallback callback));
-};
-
-class FakeConsistencyCookieManager : public ConsistencyCookieManagerBase {
- public:
-  FakeConsistencyCookieManager(SigninClient* signin_client,
-                               AccountReconcilor* reconcilor)
-      : ConsistencyCookieManagerBase(signin_client, reconcilor) {
-    UpdateCookie();
-  }
-};
-
-class ConsistencyCookieManagerTest : public ::testing::Test {
- public:
-  ConsistencyCookieManagerTest()
-      : signin_client_(&pref_service_),
-        identity_test_env_(/*test_url_loader_factory=*/nullptr,
-                           &pref_service_,
-                           AccountConsistencyMethod::kMirror,
-                           &signin_client_) {
-    scoped_feature_list_.InitAndEnableFeature(kMiceFeature);
-    std::unique_ptr<MockCookieManager> cookie_manager =
-        std::make_unique<MockCookieManager>();
-    mock_cookie_manager_ = cookie_manager.get();
-    signin_client_.set_cookie_manager(std::move(cookie_manager));
-    reconcilor_ = std::make_unique<AccountReconcilor>(
-        identity_test_env_.identity_manager(), &signin_client_,
-        std::make_unique<AccountReconcilorDelegate>());
-    reconcilor_->Initialize(/*start_reconcile_if_tokens_available=*/false);
-  }
-
-  ~ConsistencyCookieManagerTest() override { reconcilor_->Shutdown(); }
-
-  SigninClient* signin_client() { return &signin_client_; }
-  AccountReconcilor* reconcilor() { return reconcilor_.get(); }
-
-  MockCookieManager* mock_cookie_manager() {
-    DCHECK_EQ(mock_cookie_manager_, signin_client_.GetCookieManager());
-    return mock_cookie_manager_;
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  base::test::TaskEnvironment task_environment_;
-  sync_preferences::TestingPrefServiceSyncable pref_service_;
-
-  // Owned by signin_client_.
-  MockCookieManager* mock_cookie_manager_ = nullptr;
-
-  TestSigninClient signin_client_;
-  IdentityTestEnvironment identity_test_env_;
-  std::unique_ptr<AccountReconcilor> reconcilor_;
-};
-
-// Tests that the cookie is updated when the account reconcilor state changes.
-TEST_F(ConsistencyCookieManagerTest, AccountReconcilorState) {
-  // AccountReconcilor::Initialize() creates the ConsistencyCookieManager.
-  mock_cookie_manager()->ExpectSetCookieCall("Consistent");
-  reconcilor()->SetConsistencyCookieManager(
-      std::make_unique<FakeConsistencyCookieManager>(signin_client(),
-                                                     reconcilor()));
-  testing::Mock::VerifyAndClearExpectations(mock_cookie_manager());
-  ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor()->GetState());
-
-  // Trigger a state change in the reconcilor, and check that the cookie was
-  // updated accordingly. Calling EnableReconcile() will cause the reconcilor
-  // state to change to SCHEDULED then OK.
-  mock_cookie_manager()->ExpectSetCookieCall("Updating");
-  mock_cookie_manager()->ExpectSetCookieCall("Consistent");
-  reconcilor()->EnableReconcile();
-}
-
-}  // namespace
-}  // namespace signin
diff --git a/components/signin/core/browser/mice_account_reconcilor_delegate.cc b/components/signin/core/browser/mice_account_reconcilor_delegate.cc
deleted file mode 100644
index 8b8c936..0000000
--- a/components/signin/core/browser/mice_account_reconcilor_delegate.cc
+++ /dev/null
@@ -1,76 +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 "components/signin/core/browser/mice_account_reconcilor_delegate.h"
-
-#include "base/logging.h"
-
-namespace signin {
-
-MiceAccountReconcilorDelegate::MiceAccountReconcilorDelegate() = default;
-
-MiceAccountReconcilorDelegate::~MiceAccountReconcilorDelegate() = default;
-
-bool MiceAccountReconcilorDelegate::IsReconcileEnabled() const {
-  return true;
-}
-
-bool MiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
-  return true;
-}
-
-gaia::GaiaSource MiceAccountReconcilorDelegate::GetGaiaApiSource() const {
-  return gaia::GaiaSource::kAccountReconcilorMirror;
-}
-
-CoreAccountId MiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
-    const std::vector<CoreAccountId>& chrome_accounts,
-    const std::vector<gaia::ListedAccount>& gaia_accounts,
-    const CoreAccountId& primary_account,
-    bool first_execution,
-    bool will_logout) const {
-  // This flow is deprecated and will be removed when multilogin is fully
-  // launched.
-  NOTREACHED() << "Mice requires multilogin";
-  return CoreAccountId();
-}
-
-std::vector<CoreAccountId>
-MiceAccountReconcilorDelegate::GetChromeAccountsForReconcile(
-    const std::vector<CoreAccountId>& chrome_accounts,
-    const CoreAccountId& primary_account,
-    const std::vector<gaia::ListedAccount>& gaia_accounts,
-    const gaia::MultiloginMode mode) const {
-  if (chrome_accounts.empty())
-    return {};
-
-  // First account, by priority order:
-  // - primary account
-  // - first account on the device.
-  // Warning: As a result, the reconciliation may change the default Gaia
-  // account. It should be ensured that this is not surprising for the user.
-  CoreAccountId new_first_account =
-      base::Contains(chrome_accounts, primary_account) ? primary_account
-                                                       : chrome_accounts[0];
-
-  // Minimize account shuffling and ensure that the number of accounts does not
-  // exceed the limit.
-  return ReorderChromeAccountsForReconcile(chrome_accounts, new_first_account,
-                                           gaia_accounts);
-}
-
-gaia::MultiloginMode MiceAccountReconcilorDelegate::CalculateModeForReconcile(
-    const std::vector<gaia::ListedAccount>& gaia_accounts,
-    const CoreAccountId& primary_account,
-    bool first_execution,
-    bool primary_has_error) const {
-  return gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
-}
-
-bool MiceAccountReconcilorDelegate::IsUnknownInvalidAccountInCookieAllowed()
-    const {
-  return false;
-}
-
-}  // namespace signin
diff --git a/components/signin/core/browser/mice_account_reconcilor_delegate.h b/components/signin/core/browser/mice_account_reconcilor_delegate.h
deleted file mode 100644
index 28a71d00..0000000
--- a/components/signin/core/browser/mice_account_reconcilor_delegate.h
+++ /dev/null
@@ -1,50 +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 COMPONENTS_SIGNIN_CORE_BROWSER_MICE_ACCOUNT_RECONCILOR_DELEGATE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_MICE_ACCOUNT_RECONCILOR_DELEGATE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "components/signin/core/browser/account_reconcilor_delegate.h"
-
-namespace signin {
-
-// AccountReconcilorDelegate specialized for Mice.
-class MiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
- public:
-  MiceAccountReconcilorDelegate();
-  ~MiceAccountReconcilorDelegate() override;
-
- private:
-  // AccountReconcilorDelegate:
-  bool IsReconcileEnabled() const override;
-  bool IsAccountConsistencyEnforced() const override;
-  gaia::GaiaSource GetGaiaApiSource() const override;
-  CoreAccountId GetFirstGaiaAccountForReconcile(
-      const std::vector<CoreAccountId>& chrome_accounts,
-      const std::vector<gaia::ListedAccount>& gaia_accounts,
-      const CoreAccountId& primary_account,
-      bool first_execution,
-      bool will_logout) const override;
-  std::vector<CoreAccountId> GetChromeAccountsForReconcile(
-      const std::vector<CoreAccountId>& chrome_accounts,
-      const CoreAccountId& primary_account,
-      const std::vector<gaia::ListedAccount>& gaia_accounts,
-      const gaia::MultiloginMode mode) const override;
-  gaia::MultiloginMode CalculateModeForReconcile(
-      const std::vector<gaia::ListedAccount>& gaia_accounts,
-      const CoreAccountId& primary_account,
-      bool first_execution,
-      bool primary_has_error) const override;
-  bool IsUnknownInvalidAccountInCookieAllowed() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(MiceAccountReconcilorDelegate);
-};
-
-}  // namespace signin
-
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_MICE_ACCOUNT_RECONCILOR_DELEGATE_H_
diff --git a/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc b/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc
deleted file mode 100644
index b3947eaab..0000000
--- a/components/signin/core/browser/mice_account_reconcilor_delegate_unittest.cc
+++ /dev/null
@@ -1,87 +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 "components/signin/core/browser/mice_account_reconcilor_delegate.h"
-
-#include <vector>
-
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace signin {
-
-namespace {
-
-// Returns a gaia::ListedAccount with the specified account id.
-gaia::ListedAccount BuildTestListedAccount(const std::string account_id,
-                                           bool valid) {
-  gaia::ListedAccount account;
-  account.id = CoreAccountId(account_id);
-  account.valid = valid;
-  return account;
-}
-
-// Returns vector of account_id created from value
-std::vector<CoreAccountId> ToAccountIdList(
-    const std::vector<std::string>& account_ids_value) {
-  std::vector<CoreAccountId> account_ids;
-  for (const auto& account_id_value : account_ids_value)
-    account_ids.push_back(CoreAccountId(account_id_value));
-  return account_ids;
-}
-
-}  // namespace
-
-TEST(MiceAccountReconcilorDelegate, CalculateParametersForMultilogin) {
-  MiceAccountReconcilorDelegate mice_delegate;
-
-  const gaia::ListedAccount kA = BuildTestListedAccount("A", /*valid=*/true);
-  const gaia::ListedAccount kB = BuildTestListedAccount("B", /*valid=*/false);
-
-  struct TestParams {
-    std::vector<std::string> chrome_accounts;
-    std::string primary_account;
-    std::vector<gaia::ListedAccount> gaia_accounts;
-
-    std::vector<std::string> expected_accounts;
-  };
-
-  // clang-format off
-  TestParams cases[] = {
-  // chrome_accounts, primary_account, gaia_accounts, expected_accounts
-    {{},              "",              {},            {}},
-    {{},              "",              {kA, kB},      {}},
-    {{"A"},           "",              {},            {"A"}},
-    {{"A"},           "",              {kA, kB},      {"A"}},
-    {{"A"},           "",              {kB, kA},      {"A"}},
-    {{"A", "B"},      "",              {},            {"A", "B"}},
-    {{"A", "B"},      "",              {kA},          {"A", "B"}},
-    {{"A", "B"},      "",              {kB},          {"A", "B"}},
-    {{"B", "C"},      "",              {kA},          {"B", "C"}},
-    {{"A", "B"},      "",              {kA, kB},      {"A", "B"}},
-    {{"A", "B"},      "",              {kB, kA},      {"A", "B"}},
-    {{"B", "C"},      "",              {kA, kB},      {"B", "C"}},
-    // Tests the reordering: B remains in 2nd place.
-    {{"C", "D", "B"}, "",              {kA, kB},      {"C", "B", "D"}},
-    // With primary account.
-    {{"A", "B"},      "B",             {},            {"B", "A"}},
-    {{"B", "A"},      "A",             {kB, kA},      {"A", "B"}},
-    {{"A", "B"},      "B",             {kB, kA},      {"B", "A"}},
-  };
-  // clang-format on
-
-  for (const auto& test : cases) {
-    MultiloginParameters multilogin_parameters =
-        mice_delegate.CalculateParametersForMultilogin(
-            ToAccountIdList(test.chrome_accounts),
-            CoreAccountId(test.primary_account), test.gaia_accounts, false,
-            false);
-    EXPECT_EQ(gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
-              multilogin_parameters.mode);
-    EXPECT_EQ(ToAccountIdList(test.expected_accounts),
-              multilogin_parameters.accounts_to_send);
-  }
-}
-
-}  // namespace signin
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 1dcb4c5352..2f6e6a3 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -142,31 +142,12 @@
 // Tests that no Mirror request is returned when the user is not signed in (no
 // account id), for non Chrome OS platforms.
 TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) {
-#if defined(OS_ANDROID)
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndDisableFeature(kMiceFeature);
-#endif
   account_consistency_ = AccountConsistencyMethod::kMirror;
   CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", "");
   CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", "");
 }
 #endif
 
-#if defined(OS_ANDROID)
-// Tests that Mirror request is returned on Android with Mice.
-TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdMice) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(kMiceFeature);
-  account_consistency_ = AccountConsistencyMethod::kMirror;
-  CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "",
-                           "mode=0,enable_account_consistency=true,"
-                           "consistency_enabled_by_default=true");
-  CheckMirrorCookieRequest(GURL("https://docs.google.com"), "",
-                           "mode=0:enable_account_consistency=true:"
-                           "consistency_enabled_by_default=true");
-}
-#endif
-
 // Tests that no Mirror request is returned when the cookies aren't allowed to
 // be set.
 TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
diff --git a/components/signin/internal/identity_manager/account_fetcher_service.cc b/components/signin/internal/identity_manager/account_fetcher_service.cc
index b68852c..c9573c7 100644
--- a/components/signin/internal/identity_manager/account_fetcher_service.cc
+++ b/components/signin/internal/identity_manager/account_fetcher_service.cc
@@ -23,6 +23,7 @@
 #include "components/signin/public/base/avatar_icon_util.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/base/signin_switches.h"
+#include "net/http/http_status_code.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if defined(OS_ANDROID)
@@ -369,6 +370,10 @@
 void AccountFetcherService::OnImageFetched(
     const CoreAccountId& account_id,
     const gfx::Image& image,
-    const image_fetcher::RequestMetadata&) {
+    const image_fetcher::RequestMetadata& metadata) {
+  if (metadata.http_response_code != net::HTTP_OK) {
+    DCHECK(image.IsEmpty());
+    return;
+  }
   account_tracker_service_->SetAccountImage(account_id, image);
 }
diff --git a/components/tab_groups/tab_group_id.h b/components/tab_groups/tab_group_id.h
index ba577999..63c109a9 100644
--- a/components/tab_groups/tab_group_id.h
+++ b/components/tab_groups/tab_group_id.h
@@ -26,7 +26,7 @@
   bool operator!=(const TabGroupId& other) const;
   bool operator<(const TabGroupId& other) const;
 
-  base::Token token() const { return token_; }
+  const base::Token& token() const { return token_; }
 
   std::string ToString() const;
 
diff --git a/components/tab_groups/tab_group_visual_data.h b/components/tab_groups/tab_group_visual_data.h
index 2e2bc7b..6b814a9e 100644
--- a/components/tab_groups/tab_group_visual_data.h
+++ b/components/tab_groups/tab_group_visual_data.h
@@ -28,8 +28,8 @@
   TabGroupVisualData& operator=(const TabGroupVisualData& other) = default;
   TabGroupVisualData& operator=(TabGroupVisualData&& other) = default;
 
-  base::string16 title() const { return title_; }
-  tab_groups::TabGroupColorId color() const { return color_; }
+  const base::string16& title() const { return title_; }
+  const tab_groups::TabGroupColorId& color() const { return color_; }
 
   // Checks whether two instances are visually equivalent.
   bool operator==(const TabGroupVisualData& other) const {
diff --git a/components/variations/variations_murmur_hash.cc b/components/variations/variations_murmur_hash.cc
index 661dbf7..750e51d 100644
--- a/components/variations/variations_murmur_hash.cc
+++ b/components/variations/variations_murmur_hash.cc
@@ -5,6 +5,7 @@
 #include "components/variations/variations_murmur_hash.h"
 
 #include "base/compiler_specific.h"
+#include "base/logging.h"
 #include "base/sys_byteorder.h"
 #include "build/build_config.h"
 
diff --git a/components/viz/service/display/overlay_processor_win.cc b/components/viz/service/display/overlay_processor_win.cc
index 7d87aa3..d002384 100644
--- a/components/viz/service/display/overlay_processor_win.cc
+++ b/components/viz/service/display/overlay_processor_win.cc
@@ -44,8 +44,9 @@
     std::vector<gfx::Rect>* content_bounds) {
   TRACE_EVENT0("viz", "OverlayProcessorWin::ProcessForOverlays");
 
+  RenderPass* root_render_pass = render_passes->back().get();
   // Skip overlay processing if we have copy request.
-  if (!render_passes->back()->copy_requests.empty()) {
+  if (!root_render_pass->copy_requests.empty()) {
     damage_rect->Union(dc_layer_overlay_processor_
                            ->previous_frame_overlay_damage_contribution());
     // Update damage rect before calling ClearOverlayState, otherwise
@@ -54,11 +55,17 @@
     return;
   }
 
+  // Skip overlay processing if output colorspace is HDR.
+  // Since Overlay only supports NV12 and YUY2 now, HDR content (usually P010
+  // format) cannot output through overlay without format degrading.
+  if (root_render_pass->color_space.IsHDR())
+    return;
+
   if (!enable_dc_overlay_)
     return;
 
   dc_layer_overlay_processor_->Process(
-      resource_provider, gfx::RectF(render_passes->back()->output_rect),
+      resource_provider, gfx::RectF(root_render_pass->output_rect),
       render_passes, damage_rect, candidates);
 }
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 26790524..93b5f9e 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -971,6 +971,8 @@
     "indexed_db/indexed_db_callbacks.h",
     "indexed_db/indexed_db_class_factory.cc",
     "indexed_db/indexed_db_class_factory.h",
+    "indexed_db/indexed_db_compaction_task.cc",
+    "indexed_db/indexed_db_compaction_task.h",
     "indexed_db/indexed_db_connection.cc",
     "indexed_db/indexed_db_connection.h",
     "indexed_db/indexed_db_connection_coordinator.cc",
@@ -1655,12 +1657,12 @@
     "service_worker/service_worker_job_coordinator.h",
     "service_worker/service_worker_loader_helpers.cc",
     "service_worker/service_worker_loader_helpers.h",
+    "service_worker/service_worker_main_resource_handle.cc",
+    "service_worker/service_worker_main_resource_handle.h",
+    "service_worker/service_worker_main_resource_handle_core.cc",
+    "service_worker/service_worker_main_resource_handle_core.h",
     "service_worker/service_worker_metrics.cc",
     "service_worker/service_worker_metrics.h",
-    "service_worker/service_worker_navigation_handle.cc",
-    "service_worker/service_worker_navigation_handle.h",
-    "service_worker/service_worker_navigation_handle_core.cc",
-    "service_worker/service_worker_navigation_handle_core.h",
     "service_worker/service_worker_navigation_loader.cc",
     "service_worker/service_worker_navigation_loader.h",
     "service_worker/service_worker_navigation_loader_interceptor.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index b080a40..84df4845 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -17,6 +17,7 @@
   "+components/services/quarantine/test_support.h",
   "+components/services/quarantine/quarantine.h",
   "+components/services/storage",
+  "+components/services/storage/public",
   "+components/session_manager/core",
   "+components/leveldb_proto/public",
   "+components/link_header_util",
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index cabb424..0e16b551 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -42,6 +42,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/accessibility/accessibility_features.h"
+#include "ui/base/ui_base_features.h"
 
 namespace content {
 
@@ -115,6 +116,11 @@
   enabled_features.emplace_back(
       features::kEnableAccessibilityExposeDisplayNone);
 
+  // Enable the FormControlsRefresh feature to make sure the
+  // accessibility tree is the same across platforms.
+  // TODO(1012108): remove this once Mac is also enabled by default.
+  enabled_features.emplace_back(features::kFormControlsRefresh);
+
   // TODO(dmazzoni): DumpAccessibilityTree expectations are based on the
   // assumption that the accessibility labels feature is off. (There are
   // also several tests that explicitly enable the feature.) It'd be better
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index ee37f49..9f11e93 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -26,7 +26,6 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "ui/accessibility/accessibility_switches.h"
-#include "ui/base/ui_base_features.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -1574,10 +1573,8 @@
   RunHtmlTest(FILE_PATH_LITERAL("input-date.html"));
 }
 
-#if defined(OS_WIN) || defined(OS_MACOSX)
 // TODO(crbug.com/423675): AX tree is different for Win7 and Win10.
-// TODO(1038813): The /blink test pass is different on Windows and Mac, versus
-// Linux.
+#if defined(OS_WIN)
 #define MAYBE_AccessibilityInputDateWithPopupOpen \
   DISABLED_AccessibilityInputDateWithPopupOpen
 #else
@@ -1589,18 +1586,18 @@
   RunHtmlTest(FILE_PATH_LITERAL("input-date-with-popup-open.html"));
 }
 
-#if defined(OS_WIN) || defined(OS_MACOSX)
-// TODO(1038813): The /blink test pass is different on Windows and Mac, versus
-// Linux.
-#define MAYBE_AccessibilityInputDateWithPopupOpenMultiple \
-  DISABLED_AccessibilityInputDateWithPopupOpenMultiple
+// The /blink test pass is different when run on Windows vs other OSs.
+// So separate into two different tests.
+#if defined(OS_WIN)
+#define AccessibilityInputDateWithPopupOpenMultiple_TestFile \
+  FILE_PATH_LITERAL("input-date-with-popup-open-multiple-for-win.html")
 #else
-#define MAYBE_AccessibilityInputDateWithPopupOpenMultiple \
-  AccessibilityInputDateWithPopupOpenMultiple
+#define AccessibilityInputDateWithPopupOpenMultiple_TestFile \
+  FILE_PATH_LITERAL("input-date-with-popup-open-multiple.html")
 #endif
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
-                       MAYBE_AccessibilityInputDateWithPopupOpenMultiple) {
-  RunHtmlTest(FILE_PATH_LITERAL("input-date-with-popup-open-multiple.html"));
+                       AccessibilityInputDateWithPopupOpenMultiple) {
+  RunHtmlTest(AccessibilityInputDateWithPopupOpenMultiple_TestFile);
 }
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputDateTime) {
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index dcfa177a..7afe590 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -2800,7 +2800,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(BackForwardCacheBrowserTestWithServiceWorkerEnabled,
-                       CachedClientBecomesControlledByServiceWorker) {
+                       EvictOnServiceWorkerClaim) {
   net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_server.RegisterRequestHandler(
       base::BindRepeating(&RequestHandlerForUpdateWorker));
@@ -2825,7 +2825,6 @@
                             https_server.GetURL("b.com", "/title1.html")));
   EXPECT_FALSE(deleted.deleted());
   EXPECT_TRUE(rfh_a->is_in_back_forward_cache());
-  RenderFrameHostImpl* rfh_b = current_frame_host();
 
   // 3) Navigate to A in |tab_to_execute_service_worker|.
   EXPECT_TRUE(NavigateToURL(
@@ -2836,19 +2835,21 @@
   // 4) Register a service worker for |tab_to_execute_service_worker|.
   EXPECT_EQ("DONE", EvalJs(tab_to_execute_service_worker,
                            "register('service_worker_registration.js')"));
-  // 5) |rfh_a| becomes controlled by ServiceWorker by clients.claim().
+
+  // 5) The service worker calls clients.claim(). |rfh_a| would normally be
+  //    claimed but because it's in bfcache, it is evicted from the cache.
   EXPECT_EQ("DONE", EvalJs(tab_to_execute_service_worker, "claim()"));
 
-  // 5) Navigate to A in |tab_to_be_bfcached|.
+  // 6) Navigate to A in |tab_to_be_bfcached|.
   tab_to_be_bfcached->web_contents()->GetController().GoBack();
   EXPECT_TRUE(WaitForLoadStop(tab_to_be_bfcached->web_contents()));
   EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  EXPECT_FALSE(deleted.deleted());
-  EXPECT_EQ(rfh_a, current_frame_host());
-  EXPECT_FALSE(rfh_a->is_in_back_forward_cache());
-  EXPECT_TRUE(rfh_b->is_in_back_forward_cache());
-  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
+  EXPECT_TRUE(deleted.deleted());
+  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kNotRestored,
                 FROM_HERE);
+  ExpectNotRestored(
+      {BackForwardCacheMetrics::NotRestoredReason::kServiceWorkerClaim},
+      FROM_HERE);
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index 39a2bff..82a6da6 100644
--- a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -148,7 +148,7 @@
     const UUIDSet& device_uuids,
     const base::Optional<
         std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>>& filters) {
-  DCHECK(!HasEmptyOrInvalidFilter(filters));
+  DCHECK(HasValidFilter(filters));
   for (const auto& filter : filters.value()) {
     if (MatchesFilter(device_name, device_uuids, filter)) {
       return true;
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 9eae00e3..56e24f0 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -129,57 +129,54 @@
 // the maximum device name length is 248 bytes (UTF-8 encoded).
 constexpr size_t kMaxLengthForDeviceName = 248;
 
-bool IsEmptyOrInvalidFilter(
-    const blink::mojom::WebBluetoothLeScanFilterPtr& filter) {
+bool IsValidFilter(const blink::mojom::WebBluetoothLeScanFilterPtr& filter) {
   // At least one member needs to be present.
   if (!filter->name && !filter->name_prefix && !filter->services)
-    return true;
+    return false;
 
   // The renderer will never send a |name| or a |name_prefix| longer than
   // kMaxLengthForDeviceName.
   if (filter->name && filter->name->size() > kMaxLengthForDeviceName)
-    return true;
+    return false;
 
   if (filter->name_prefix &&
       filter->name_prefix->size() > kMaxLengthForDeviceName)
-    return true;
+    return false;
 
   // The |name_prefix| should not be empty
   if (filter->name_prefix && filter->name_prefix->empty())
-    return true;
+    return false;
 
-  return false;
+  return true;
 }
 
-bool IsRequestDeviceOptionsInvalid(
+bool IsValidRequestDeviceOptions(
     const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
   if (options->accept_all_devices)
-    return options->filters.has_value();
+    return !options->filters.has_value();
 
-  return HasEmptyOrInvalidFilter(options->filters);
+  return HasValidFilter(options->filters);
 }
 
-bool IsRequestScanOptionsInvalid(
+bool IsValidRequestScanOptions(
     const blink::mojom::WebBluetoothRequestLEScanOptionsPtr& options) {
   if (options->accept_all_advertisements)
-    return options->filters.has_value();
+    return !options->filters.has_value();
 
-  return HasEmptyOrInvalidFilter(options->filters);
+  return HasValidFilter(options->filters);
 }
 
 }  // namespace
 
-bool HasEmptyOrInvalidFilter(
+bool HasValidFilter(
     const base::Optional<
         std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>>& filters) {
   if (!filters) {
-    return true;
+    return false;
   }
 
-  return filters->empty()
-             ? true
-             : filters->end() != std::find_if(filters->begin(), filters->end(),
-                                              IsEmptyOrInvalidFilter);
+  return !filters->empty() &&
+         std::all_of(filters->begin(), filters->end(), IsValidFilter);
 }
 
 // Struct that holds the result of a cache query.
@@ -1247,7 +1244,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // The renderer should never send invalid options.
-  if (IsRequestScanOptionsInvalid(options)) {
+  if (!IsValidRequestScanOptions(options)) {
     CrashRendererAndClosePipe(bad_message::BDH_INVALID_OPTIONS);
     return;
   }
@@ -1363,7 +1360,7 @@
     RequestDeviceCallback callback,
     scoped_refptr<device::BluetoothAdapter> adapter) {
   // The renderer should never send invalid options.
-  if (IsRequestDeviceOptionsInvalid(options)) {
+  if (!IsValidRequestDeviceOptions(options)) {
     CrashRendererAndClosePipe(bad_message::BDH_INVALID_OPTIONS);
     return;
   }
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index 0f402994..ee4c1bf 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -44,7 +44,7 @@
 class RenderFrameHost;
 class RenderProcessHost;
 
-bool HasEmptyOrInvalidFilter(
+bool HasValidFilter(
     const base::Optional<
         std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>>& filters);
 
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index c7a95973..3d20f3d 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -672,7 +672,7 @@
   modifiers |= button_modifiers;
   base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
 
-  std::unique_ptr<blink::WebMouseEvent> mouse_event;
+  std::unique_ptr<blink::WebMouseEvent, ui::WebInputEventDeleter> mouse_event;
   blink::WebMouseWheelEvent* wheel_event = nullptr;
 
   if (type == blink::WebInputEvent::kMouseWheel) {
diff --git a/content/browser/frame_host/back_forward_cache_can_store_document_result.cc b/content/browser/frame_host/back_forward_cache_can_store_document_result.cc
index 9749e8a..9775b3c 100644
--- a/content/browser/frame_host/back_forward_cache_can_store_document_result.cc
+++ b/content/browser/frame_host/back_forward_cache_can_store_document_result.cc
@@ -116,6 +116,8 @@
       return "RenderFrameHost is reused for a cross-site navigation";
     case Reason::kNotMostRecentNavigationEntry:
       return "navigation entry is not the most recent one for this document";
+    case Reason::kServiceWorkerClaim:
+      return "service worker claim is called";
   }
 }
 
diff --git a/content/browser/frame_host/back_forward_cache_metrics.h b/content/browser/frame_host/back_forward_cache_metrics.h
index 7837403..bbebb10 100644
--- a/content/browser/frame_host/back_forward_cache_metrics.h
+++ b/content/browser/frame_host/back_forward_cache_metrics.h
@@ -71,7 +71,8 @@
     kRenderFrameHostReused_SameSite = 27,
     kRenderFrameHostReused_CrossSite = 28,
     kNotMostRecentNavigationEntry = 29,
-    kMaxValue = kNotMostRecentNavigationEntry,
+    kServiceWorkerClaim = 30,
+    kMaxValue = kServiceWorkerClaim,
   };
 
   using NotRestoredReasons =
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 828c506..550c96e 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -46,7 +46,7 @@
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/browser/web_package/prefetched_signed_exchange_cache.h"
 #include "content/browser/web_package/web_bundle_handle_tracker.h"
@@ -2010,8 +2010,8 @@
   // comment in the header for |loader_|.
   DCHECK(!loader_);
 
-  // Only initialize the ServiceWorkerNavigationHandle if it can be created for
-  // this frame.
+  // Only initialize the ServiceWorkerMainResourceHandle if it can be created
+  // for this frame.
   bool can_create_service_worker =
       (frame_tree_node_->pending_frame_policy().sandbox_flags &
        blink::WebSandboxFlags::kOrigin) != blink::WebSandboxFlags::kOrigin;
@@ -2019,8 +2019,8 @@
     ServiceWorkerContextWrapper* service_worker_context =
         static_cast<ServiceWorkerContextWrapper*>(
             partition->GetServiceWorkerContext());
-    service_worker_handle_ =
-        std::make_unique<ServiceWorkerNavigationHandle>(service_worker_context);
+    service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
+        service_worker_context);
   }
 
   if (IsSchemeSupportedForAppCache(common_params_->url)) {
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index c4b65d7..8c73beb 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -65,7 +65,7 @@
 class NavigationUIData;
 class NavigatorDelegate;
 class PrefetchedSignedExchangeCache;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class SiteInstanceImpl;
 struct SubresourceLoaderParams;
 
@@ -1063,7 +1063,7 @@
 
   // Manages the lifetime of a pre-created ServiceWorkerProviderHost until a
   // corresponding provider is created in the renderer.
-  std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
 
   // Timer for detecting an unexpectedly long time to commit a navigation.
   base::OneShotTimer commit_timeout_timer_;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 1e5029c..cd6aea1 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -7415,7 +7415,8 @@
   DCHECK(navigation_client && navigation_request);
   navigation_client->CommitFailedNavigation(
       std::move(common_params), std::move(commit_params),
-      has_stale_copy_in_cache, error_code, error_page_content,
+      has_stale_copy_in_cache, error_code,
+      navigation_request->GetResolveErrorInfo(), error_page_content,
       std::move(subresource_loader_factories),
       BuildCommitFailedNavigationCallback(navigation_request));
 }
diff --git a/content/browser/indexed_db/indexed_db_compaction_task.cc b/content/browser/indexed_db/indexed_db_compaction_task.cc
new file mode 100644
index 0000000..c8484df
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_compaction_task.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_compaction_task.h"
+
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+
+namespace content {
+
+IndexedDBCompactionTask::IndexedDBCompactionTask(leveldb::DB* database)
+    : IndexedDBPreCloseTaskQueue::PreCloseTask(database) {}
+
+IndexedDBCompactionTask::~IndexedDBCompactionTask() = default;
+
+bool IndexedDBCompactionTask::RequiresMetadata() const {
+  return false;
+}
+
+void IndexedDBCompactionTask::Stop(
+    IndexedDBPreCloseTaskQueue::StopReason reason) {}
+
+bool IndexedDBCompactionTask::RunRound() {
+  database()->CompactRange(nullptr, nullptr);
+  return true;
+}
+
+}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_compaction_task.h b/content/browser/indexed_db/indexed_db_compaction_task.h
new file mode 100644
index 0000000..3b5a438
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_compaction_task.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_COMPACTION_TASK_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_COMPACTION_TASK_H_
+
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+
+namespace leveldb {
+class DB;
+}  // namespace leveldb
+
+namespace content {
+
+class IndexedDBCompactionTask
+    : public IndexedDBPreCloseTaskQueue::PreCloseTask {
+ public:
+  explicit IndexedDBCompactionTask(leveldb::DB* database);
+  ~IndexedDBCompactionTask() override;
+
+  bool RequiresMetadata() const override;
+
+  void Stop(IndexedDBPreCloseTaskQueue::StopReason reason) override;
+
+  bool RunRound() override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_COMPACTION_TASK_H_
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index b5fb6d0..200fdfd 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -110,6 +110,25 @@
       base::MakeRefCounted<IndexedDBQuotaClient>(this));
 }
 
+void IndexedDBContextImpl::Bind(
+    mojo::PendingReceiver<storage::mojom::IndexedDBControl> control) {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  receivers_.Add(this, std::move(control));
+}
+
+void IndexedDBContextImpl::GetUsage(GetUsageCallback usage_callback) {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  std::vector<Origin> origins = GetAllOrigins();
+  std::vector<storage::mojom::IndexedDBStorageUsageInfoPtr> result;
+  for (const auto& origin : origins) {
+    storage::mojom::IndexedDBStorageUsageInfoPtr usage_info =
+        storage::mojom::IndexedDBStorageUsageInfo::New(
+            origin, GetOriginDiskUsage(origin), GetOriginLastModified(origin));
+    result.push_back(std::move(usage_info));
+  }
+  std::move(usage_callback).Run(std::move(result));
+}
+
 IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   if (!indexeddb_factory_.get()) {
@@ -122,6 +141,11 @@
   return indexeddb_factory_.get();
 }
 
+base::SequencedTaskRunner* IndexedDBContextImpl::IOTaskRunner() {
+  DCHECK(io_task_runner_.get());
+  return io_task_runner_.get();
+}
+
 std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   std::set<Origin>* origins_set = GetOriginSet();
@@ -134,17 +158,6 @@
   return set->find(origin) != set->end();
 }
 
-std::vector<StorageUsageInfo> IndexedDBContextImpl::GetAllOriginsInfo() {
-  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  std::vector<Origin> origins = GetAllOrigins();
-  std::vector<StorageUsageInfo> result;
-  for (const auto& origin : origins) {
-    result.push_back(StorageUsageInfo(origin, GetOriginDiskUsage(origin),
-                                      GetOriginLastModified(origin)));
-  }
-  return result;
-}
-
 static bool HostNameComparator(const Origin& i, const Origin& j) {
   return i.host() < j.host();
 }
@@ -633,9 +646,4 @@
   return idb_task_runner_.get();
 }
 
-base::SequencedTaskRunner* IndexedDBContextImpl::IOTaskRunner() {
-  DCHECK(io_task_runner_.get());
-  return io_task_runner_.get();
-}
-
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index e16134fe..c67392a 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -18,9 +18,11 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/public/browser/indexed_db_context.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "storage/browser/quota/special_storage_policy.h"
 #include "url/origin.h"
@@ -40,7 +42,9 @@
 class IndexedDBConnection;
 class IndexedDBFactoryImpl;
 
-class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
+class CONTENT_EXPORT IndexedDBContextImpl
+    : public IndexedDBContext,
+      public storage::mojom::IndexedDBControl {
  public:
   // Recorded in histograms, so append only.
   enum ForceCloseReason {
@@ -79,18 +83,22 @@
       scoped_refptr<base::SequencedTaskRunner> io_task_runner,
       scoped_refptr<base::SequencedTaskRunner> custom_task_runner);
 
+  void Bind(mojo::PendingReceiver<storage::mojom::IndexedDBControl> control);
+
+  // mojom::IndexedDBControl implementation:
+  void GetUsage(GetUsageCallback usage_callback) override;
+
   IndexedDBFactoryImpl* GetIDBFactory();
 
+  base::SequencedTaskRunner* IOTaskRunner();
+
   // Called by StoragePartitionImpl to clear session-only data.
   void Shutdown();
 
-
   int64_t GetOriginDiskUsage(const url::Origin& origin);
 
   // IndexedDBContext implementation:
   base::SequencedTaskRunner* IDBTaskRunner() override;
-  base::SequencedTaskRunner* IOTaskRunner() override;
-  std::vector<StorageUsageInfo> GetAllOriginsInfo() override;
   void DeleteForOrigin(const url::Origin& origin) override;
   void CopyOriginData(const url::Origin& origin,
                       IndexedDBContext* dest_context) override;
@@ -196,6 +204,8 @@
   base::ObserverList<Observer>::Unchecked observers_;
   base::Clock* clock_;
 
+  mojo::ReceiverSet<storage::mojom::IndexedDBControl> receivers_;
+
   DISALLOW_COPY_AND_ASSIGN(IndexedDBContextImpl);
 };
 
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 40c910ba..19bdd95 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -274,19 +274,6 @@
   transaction_receivers_.Add(std::move(transaction), std::move(receiver));
 }
 
-void IndexedDBDispatcherHost::RenderProcessExited(
-    RenderProcessHost* host,
-    const ChildProcessTerminationInfo& info) {
-  // Since |this| is destructed on the IDB task runner, the next call would be
-  // issued and run before any destruction event.  This guarantees that the
-  // base::Unretained(this) usage is safe below.
-  IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &IndexedDBDispatcherHost::InvalidateWeakPtrsAndClearBindings,
-          base::Unretained(this)));
-}
-
 void IndexedDBDispatcherHost::GetDatabaseInfo(
     mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
         pending_callbacks) {
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index 030db2b..8f51d9aa 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -41,9 +41,7 @@
 
 // Constructed on UI thread.  All remaining calls (including destruction) should
 // happen on the IDB sequenced task runner.
-class CONTENT_EXPORT IndexedDBDispatcherHost
-    : public blink::mojom::IDBFactory,
-      public RenderProcessHostObserver {
+class CONTENT_EXPORT IndexedDBDispatcherHost : public blink::mojom::IDBFactory {
  public:
   // Only call the constructor from the UI thread.
   IndexedDBDispatcherHost(
@@ -106,11 +104,6 @@
   void CreateAllBlobs(const std::vector<IndexedDBBlobInfo>& blob_infos,
                       std::vector<blink::mojom::IDBBlobInfoPtr>* output_infos);
 
-  // Called by UI thread. Used to kill outstanding bindings and weak pointers
-  // in callbacks.
-  void RenderProcessExited(RenderProcessHost* host,
-                           const ChildProcessTerminationInfo& info) override;
-
  private:
   class IDBSequenceHelper;
   // Friends to enable OnDestruct() delegation.
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 9646eef9..ae87c57 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/time/default_clock.h"
 #include "components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom-test-utils.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -251,7 +252,10 @@
   EXPECT_TRUE(origin_state2_handle.IsHeld()) << s.ToString();
   EXPECT_TRUE(s.ok()) << s.ToString();
 
-  std::vector<StorageUsageInfo> origin_info = context()->GetAllOriginsInfo();
+  std::vector<storage::mojom::IndexedDBStorageUsageInfoPtr> origin_info;
+  storage::mojom::IndexedDBControlAsyncWaiter sync_control(context());
+  sync_control.GetUsage(&origin_info);
+
   EXPECT_EQ(2ul, origin_info.size());
   EXPECT_EQ(2ul, factory()->GetOpenOrigins().size());
 }
@@ -301,7 +305,6 @@
 }
 
 TEST_F(IndexedDBFactoryTestWithMockTime, PreCloseTasksStart) {
-  base::test::ScopedFeatureList feature_list;
   base::SimpleTestClock clock;
   clock.SetNow(base::Time::Now());
   SetupContextWithFactories(nullptr, &clock);
@@ -325,73 +328,73 @@
   EXPECT_EQ(IndexedDBOriginState::ClosingState::kPreCloseGracePeriod,
             factory()->GetOriginFactory(origin)->closing_stage());
 
-  task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(2));
-
-  // The factory should be closed, as the pre close tasks are delayed.
-  EXPECT_FALSE(factory()->GetOriginFactory(origin));
-
-  // Move the clock to run the tasks in the next close sequence.
-  clock.Advance(IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow);
-
-  // Open a connection & immediately release it to cause the closing sequence to
-  // start again.
-  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
-      factory()->GetOrOpenOriginFactory(origin, context()->data_path(),
-                                        /*create_if_missing=*/true);
-  EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
-  origin_state_handle.Release();
-
-  // Manually execute the timer so that the PreCloseTaskList task doesn't also
-  // run.
   factory()->GetOriginFactory(origin)->close_timer()->FireNow();
 
-  // The pre-close tasks should be running now.
+  // Since the compaction task always runs, the test assumes it is running.
   ASSERT_TRUE(factory()->GetOriginFactory(origin));
   EXPECT_EQ(IndexedDBOriginState::ClosingState::kRunningPreCloseTasks,
             factory()->GetOriginFactory(origin)->closing_stage());
   ASSERT_TRUE(factory()->GetOriginFactory(origin)->pre_close_task_queue());
   EXPECT_TRUE(
       factory()->GetOriginFactory(origin)->pre_close_task_queue()->started());
+}
 
-  // Stop sweep by opening a connection.
+TEST_F(IndexedDBFactoryTestWithMockTime, TombstoneSweeperTiming) {
+  base::SimpleTestClock clock;
+  clock.SetNow(base::Time::Now());
+  SetupContextWithFactories(nullptr, &clock);
+
+  const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+  IndexedDBOriginStateHandle origin_state_handle;
+  leveldb::Status s;
+
+  // Open a connection & immediately release it to cause the closing sequence to
+  // start.
   std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path(),
                                         /*create_if_missing=*/true);
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
-  EXPECT_FALSE(
-      OriginStateFromHandle(origin_state_handle)->pre_close_task_queue());
-  origin_state_handle.Release();
+
+  // The factory should be closed, as the pre close tasks are delayed.
+  EXPECT_FALSE(origin_state_handle.origin_state()->ShouldRunTombstoneSweeper());
+
+  // Move the clock to run the tasks in the next close sequence.
+  clock.Advance(IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow);
+
+  EXPECT_TRUE(origin_state_handle.origin_state()->ShouldRunTombstoneSweeper());
 
   // Move clock forward to trigger next sweep, but origin has longer
   // sweep minimum, so no tasks should execute.
   clock.Advance(IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow);
 
-  origin_state_handle.Release();
-  EXPECT_TRUE(factory()->GetOriginFactory(origin));
-  EXPECT_EQ(IndexedDBOriginState::ClosingState::kPreCloseGracePeriod,
-            factory()->GetOriginFactory(origin)->closing_stage());
-
-  // Manually execute the timer so that the PreCloseTaskList task doesn't also
-  // run.
-  factory()->GetOriginFactory(origin)->close_timer()->FireNow();
-  EXPECT_TRUE(factory()->GetOriginFactory(origin));
-  RunPostedTasks();
-  EXPECT_FALSE(factory()->GetOriginFactory(origin));
+  EXPECT_FALSE(origin_state_handle.origin_state()->ShouldRunTombstoneSweeper());
 
   //  Finally, move the clock forward so the origin should allow a sweep.
   clock.Advance(IndexedDBOriginState::kMaxEarliestOriginSweepFromNow);
+
+  EXPECT_TRUE(origin_state_handle.origin_state()->ShouldRunTombstoneSweeper());
+}
+
+// Remove this test when the kill switch is removed.
+TEST_F(IndexedDBFactoryTest, CompactionKillSwitchWorks) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitWithFeatures({}, {kCompactIDBOnClose});
+
+  SetupContext();
+
+  const Origin origin = Origin::Create(GURL("http://localhost:81"));
+  IndexedDBOriginStateHandle origin_state_handle;
+  leveldb::Status s;
+
+  // Open a connection & immediately release it to cause the closing sequence to
+  // start.
   std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path(),
                                         /*create_if_missing=*/true);
-  origin_state_handle.Release();
-  factory()->GetOriginFactory(origin)->close_timer()->FireNow();
+  EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
 
-  ASSERT_TRUE(factory()->GetOriginFactory(origin));
-  EXPECT_EQ(IndexedDBOriginState::ClosingState::kRunningPreCloseTasks,
-            factory()->GetOriginFactory(origin)->closing_stage());
-  ASSERT_TRUE(factory()->GetOriginFactory(origin)->pre_close_task_queue());
-  EXPECT_TRUE(
-      factory()->GetOriginFactory(origin)->pre_close_task_queue()->started());
+  EXPECT_FALSE(origin_state_handle.origin_state()->ShouldRunCompaction());
 }
 
 TEST_F(IndexedDBFactoryTest, InMemoryFactoriesStay) {
diff --git a/content/browser/indexed_db/indexed_db_origin_state.cc b/content/browser/indexed_db/indexed_db_origin_state.cc
index de1fd3d0..2bd391c 100644
--- a/content/browser/indexed_db/indexed_db_origin_state.cc
+++ b/content/browser/indexed_db/indexed_db_origin_state.cc
@@ -19,6 +19,7 @@
 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/indexed_db_compaction_task.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_database.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
@@ -73,6 +74,9 @@
 
 }  // namespace
 
+const base::Feature kCompactIDBOnClose{"CompactIndexedDBOnClose",
+                                       base::FEATURE_ENABLED_BY_DEFAULT};
+
 constexpr const base::TimeDelta
     IndexedDBOriginState::kMaxEarliestGlobalSweepFromNow;
 constexpr const base::TimeDelta
@@ -305,22 +309,47 @@
       },
       weak_factory_.GetWeakPtr()));
 
-  base::Time now = clock_->Now();
+  std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks;
 
+  if (ShouldRunTombstoneSweeper()) {
+    tasks.push_back(std::make_unique<IndexedDBTombstoneSweeper>(
+        kTombstoneSweeperRoundIterations, kTombstoneSweeperMaxIterations,
+        backing_store_->db()->db()));
+  }
+
+  if (ShouldRunCompaction()) {
+    tasks.push_back(
+        std::make_unique<IndexedDBCompactionTask>(backing_store_->db()->db()));
+  }
+
+  if (!tasks.empty()) {
+    pre_close_task_queue_ = std::make_unique<IndexedDBPreCloseTaskQueue>(
+        std::move(tasks), maybe_close_backing_store_runner.Release(),
+        base::TimeDelta::FromSeconds(kRunningPreCloseTasksMaxRunPeriodSeconds),
+        std::make_unique<base::OneShotTimer>());
+    pre_close_task_queue_->Start(
+        base::BindOnce(&IndexedDBBackingStore::GetCompleteMetadata,
+                       base::Unretained(backing_store_.get())));
+  }
+}
+
+bool IndexedDBOriginState::ShouldRunTombstoneSweeper() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::Time now = clock_->Now();
   // Check that the last sweep hasn't run too recently.
   if (*earliest_global_sweep_time_ > now)
-    return;
+    return false;
 
   base::Time origin_earliest_sweep;
   leveldb::Status s = indexed_db::GetEarliestSweepTime(backing_store_->db(),
                                                        &origin_earliest_sweep);
   // TODO(dmurph): Log this or report to UMA.
   if (!s.ok() && !s.IsNotFound())
-    return;
+    return false;
 
   // This origin hasn't been swept too recently.
   if (origin_earliest_sweep > now)
-    return;
+    return false;
 
   // A sweep will happen now, so reset the sweep timers.
   *earliest_global_sweep_time_ = GenerateNextGlobalSweepTime(now);
@@ -331,27 +360,18 @@
                                        GenerateNextOriginSweepTime(now));
   // TODO(dmurph): Log this or report to UMA.
   if (!s.ok())
-    return;
+    return false;
   s = txn->Commit();
 
   // TODO(dmurph): Log this or report to UMA.
   if (!s.ok())
-    return;
+    return false;
+  return true;
+}
 
-  std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks;
-  tasks.push_back(std::make_unique<IndexedDBTombstoneSweeper>(
-      kTombstoneSweeperRoundIterations, kTombstoneSweeperMaxIterations,
-      backing_store_->db()->db()));
-  // TODO(dmurph): Add compaction task that compacts all indexes if we have
-  // more than X deletions.
-
-  pre_close_task_queue_ = std::make_unique<IndexedDBPreCloseTaskQueue>(
-      std::move(tasks), maybe_close_backing_store_runner.Release(),
-      base::TimeDelta::FromSeconds(kRunningPreCloseTasksMaxRunPeriodSeconds),
-      std::make_unique<base::OneShotTimer>());
-  pre_close_task_queue_->Start(
-      base::BindOnce(&IndexedDBBackingStore::GetCompleteMetadata,
-                     base::Unretained(backing_store_.get())));
+bool IndexedDBOriginState::ShouldRunCompaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return base::FeatureList::IsEnabled(kCompactIDBOnClose);
 }
 
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_origin_state.h b/content/browser/indexed_db/indexed_db_origin_state.h
index cf084b1..b2a6cc9 100644
--- a/content/browser/indexed_db/indexed_db_origin_state.h
+++ b/content/browser/indexed_db/indexed_db_origin_state.h
@@ -10,6 +10,8 @@
 
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
+#include "base/feature_list.h"
+#include "base/gtest_prod_util.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string16.h"
 #include "base/time/clock.h"
@@ -30,6 +32,10 @@
 
 constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately";
 
+// This is an emergency kill switch to use with Finch if the feature needs to be
+// shut off.
+CONTENT_EXPORT extern const base::Feature kCompactIDBOnClose;
+
 // IndexedDBOriginState manages the per-origin IndexedDB state, and contains the
 // backing store for the origin.
 //
@@ -149,6 +155,13 @@
   friend IndexedDBFactoryImpl;
   friend IndexedDBOriginStateHandle;
 
+  // Test needs access to ShouldRunTombstoneSweeper.
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTestWithMockTime,
+                           TombstoneSweeperTiming);
+
+  // Test needs access to CompactionKillSwitchWorks.
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, CompactionKillSwitchWorks);
+
   IndexedDBDatabase* AddDatabase(const base::string16& name,
                                  std::unique_ptr<IndexedDBDatabase> database);
 
@@ -168,6 +181,13 @@
 
   void CloseAndDestruct();
 
+  // Executes database operations, and if |true| is returned by this function,
+  // then the current time will be written to the database as the last sweep
+  // time.
+  bool ShouldRunTombstoneSweeper();
+
+  bool ShouldRunCompaction();
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   url::Origin origin_;
diff --git a/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc b/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
index bf44df2..976af6d 100644
--- a/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
+++ b/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
@@ -16,7 +16,17 @@
 
 namespace content {
 
-IndexedDBPreCloseTaskQueue::PreCloseTask::~PreCloseTask() {}
+IndexedDBPreCloseTaskQueue::PreCloseTask::PreCloseTask(leveldb::DB* database)
+    : database_(database) {}
+
+IndexedDBPreCloseTaskQueue::PreCloseTask::~PreCloseTask() = default;
+
+bool IndexedDBPreCloseTaskQueue::PreCloseTask::RequiresMetadata() const {
+  return false;
+}
+
+void IndexedDBPreCloseTaskQueue::PreCloseTask::SetMetadata(
+    const std::vector<blink::IndexedDBDatabaseMetadata>* metadata) {}
 
 IndexedDBPreCloseTaskQueue::IndexedDBPreCloseTaskQueue(
     std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks,
@@ -28,7 +38,7 @@
       timeout_time_(max_run_time),
       timeout_timer_(std::move(timer)),
       task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
-IndexedDBPreCloseTaskQueue::~IndexedDBPreCloseTaskQueue() {}
+IndexedDBPreCloseTaskQueue::~IndexedDBPreCloseTaskQueue() = default;
 
 void IndexedDBPreCloseTaskQueue::StopForNewConnection() {
   if (!started_ || done_)
@@ -41,9 +51,7 @@
   OnComplete();
 }
 
-void IndexedDBPreCloseTaskQueue::Start(
-    base::OnceCallback<leveldb::Status(std::vector<IndexedDBDatabaseMetadata>*)>
-        metadata_fetcher) {
+void IndexedDBPreCloseTaskQueue::Start(MetadataFetcher metadata_fetcher) {
   DCHECK(!started_);
   started_ = true;
   if (tasks_.empty()) {
@@ -54,12 +62,7 @@
       FROM_HERE, timeout_time_,
       base::BindOnce(&IndexedDBPreCloseTaskQueue::StopForTimout,
                      ptr_factory_.GetWeakPtr()));
-  leveldb::Status status = std::move(metadata_fetcher).Run(&metadata_);
-  if (!status.ok()) {
-    StopForMetadataError(status);
-    return;
-  }
-  tasks_.front()->SetMetadata(&metadata_);
+  metadata_fetcher_ = std::move(metadata_fetcher);
   task_runner_->PostTask(FROM_HERE,
                          base::BindOnce(&IndexedDBPreCloseTaskQueue::RunLoop,
                                         ptr_factory_.GetWeakPtr()));
@@ -110,14 +113,26 @@
     return;
   }
 
-  bool done = tasks_.front()->RunRound();
+  PreCloseTask* task = tasks_.front().get();
+  if (task->RequiresMetadata() && !task->set_metadata_was_called_) {
+    if (!has_metadata_) {
+      leveldb::Status status = std::move(metadata_fetcher_).Run(&metadata_);
+      has_metadata_ = true;
+      if (!status.ok()) {
+        StopForMetadataError(status);
+        return;
+      }
+    }
+    task->SetMetadata(&metadata_);
+    task->set_metadata_was_called_ = true;
+  }
+  bool done = task->RunRound();
   if (done) {
     tasks_.pop_front();
     if (tasks_.empty()) {
       OnComplete();
       return;
     }
-    tasks_.front()->SetMetadata(&metadata_);
   }
   task_runner_->PostTask(FROM_HERE,
                          base::BindOnce(&IndexedDBPreCloseTaskQueue::RunLoop,
diff --git a/content/browser/indexed_db/indexed_db_pre_close_task_queue.h b/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
index c406dc3..eec9bb7 100644
--- a/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
+++ b/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
@@ -21,6 +21,10 @@
 struct IndexedDBDatabaseMetadata;
 }
 
+namespace leveldb {
+class DB;
+}
+
 namespace content {
 
 // Holds a queue of PreCloseTask's to be run after an IndexedDBBackingStore no
@@ -32,6 +36,11 @@
 // Owned by IndexedDBBackingStore.
 class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
  public:
+  // This function should fetch all database metadata for the origin. The
+  // returned status signifies if the metadata was read successfully.
+  using MetadataFetcher = base::OnceCallback<leveldb::Status(
+      std::vector<blink::IndexedDBDatabaseMetadata>*)>;
+
   enum class StopReason {
     // A new connection was made to the closing backing store.
     NEW_CONNECTION,
@@ -48,11 +57,19 @@
   // used on the same SequencedTaskRunner.
   class CONTENT_EXPORT PreCloseTask {
    public:
+    explicit PreCloseTask(leveldb::DB* database);
     virtual ~PreCloseTask();
 
+    leveldb::DB* database() { return database_; }
+
+    // Implementations should override if they need database metadata. If
+    // overridden to return true, the metadata will be loaded and SetMetadata()
+    // will be called once before the first call to RunRound().
+    virtual bool RequiresMetadata() const;
+
     // Called before RunRound. |metadata| is guaranteed to outlive this task.
     virtual void SetMetadata(
-        std::vector<blink::IndexedDBDatabaseMetadata> const* metadata) = 0;
+        const std::vector<blink::IndexedDBDatabaseMetadata>* metadata);
 
     // Tells the task to stop before completion. It will be destroyed after this
     // call. Can be called at any time.
@@ -61,6 +78,14 @@
     // Runs a round of work. Tasks are expected to keep round execution time
     // small. Returns if the task is complete and can be destroyed.
     virtual bool RunRound() = 0;
+
+   private:
+    friend class IndexedDBPreCloseTaskQueue;
+
+    bool set_metadata_was_called_ = false;
+    // Raw pointer is safe because |database_| is owned by the
+    // IndexedDBOriginState.
+    leveldb::DB* const database_;
   };
 
   // |on_complete| must not contain a refptr to the IndexedDBBackingStore, as
@@ -80,10 +105,9 @@
   // immediately called.
   void StopForNewConnection();
 
-  // Starts running tasks. Can only be called once.
-  void Start(
-      base::OnceCallback<leveldb::Status(
-          std::vector<blink::IndexedDBDatabaseMetadata>*)> metadata_fetcher);
+  // Starts running tasks. Can only be called once. MetadataFetcher is expected
+  // to load the metadata from the database on disk.
+  void Start(MetadataFetcher metadata_fetcher);
 
  private:
   void OnComplete();
@@ -93,6 +117,11 @@
 
   void RunLoop();
 
+  bool has_metadata_ = false;
+  // This callback is populated when |Start| is called, and executed if a
+  // pre-close task requires metadata (see RequiresMetadata). This happens
+  // before that task is run.
+  MetadataFetcher metadata_fetcher_;
   std::vector<blink::IndexedDBDatabaseMetadata> metadata_;
 
   bool started_ = false;
diff --git a/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc b/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
index 448f275..ae68442 100644
--- a/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
@@ -41,11 +41,13 @@
 
 class MockPreCloseTask : public PreCloseTask {
  public:
-  MockPreCloseTask() {}
-  ~MockPreCloseTask() override {}
+  MockPreCloseTask() : PreCloseTask(nullptr) {}
+  ~MockPreCloseTask() override = default;
+
+  bool RequiresMetadata() const override { return true; }
 
   MOCK_METHOD1(SetMetadata,
-               void(std::vector<IndexedDBDatabaseMetadata> const* metadata));
+               void(const std::vector<IndexedDBDatabaseMetadata>* metadata));
 
   MOCK_METHOD1(Stop, void(StopReason reason));
 
@@ -228,9 +230,6 @@
   MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
   MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
 
-  EXPECT_CALL(*task1,
-              SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
-
   base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
   std::list<std::unique_ptr<PreCloseTask>> tasks;
   tasks.push_back(base::WrapUnique(task1));
@@ -249,7 +248,7 @@
 
   task_environment_.RunUntilIdle();
 
-  EXPECT_TRUE(metadata_called);
+  EXPECT_FALSE(metadata_called);
   EXPECT_TRUE(done_called);
   EXPECT_TRUE(queue.started());
   EXPECT_TRUE(queue.done());
@@ -321,8 +320,6 @@
 
     EXPECT_CALL(*task1, RunRound())
         .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
-    EXPECT_CALL(*task2,
-                SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
 
     loop.Run();
   }
@@ -367,8 +364,6 @@
 
     EXPECT_CALL(*task1, RunRound())
         .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
-    EXPECT_CALL(*task2,
-                SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
 
     loop.Run();
   }
diff --git a/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc b/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
index 5ea34d1c..c1a7e79 100644
--- a/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
+++ b/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
@@ -72,9 +72,9 @@
 IndexedDBTombstoneSweeper::IndexedDBTombstoneSweeper(int round_iterations,
                                                      int max_iterations,
                                                      leveldb::DB* database)
-    : max_round_iterations_(round_iterations),
-      max_iterations_(max_iterations),
-      database_(database) {
+    : IndexedDBPreCloseTaskQueue::PreCloseTask(database),
+      max_round_iterations_(round_iterations),
+      max_iterations_(max_iterations) {
   sweep_state_.start_database_seed = static_cast<size_t>(base::RandUint64());
   sweep_state_.start_object_store_seed =
       static_cast<size_t>(base::RandUint64());
@@ -83,8 +83,12 @@
 
 IndexedDBTombstoneSweeper::~IndexedDBTombstoneSweeper() {}
 
+bool IndexedDBTombstoneSweeper::RequiresMetadata() const {
+  return true;
+}
+
 void IndexedDBTombstoneSweeper::SetMetadata(
-    std::vector<IndexedDBDatabaseMetadata> const* metadata) {
+    const std::vector<IndexedDBDatabaseMetadata>* metadata) {
   database_metadata_ = metadata;
   total_indices_ = 0;
   for (const auto& db : *metadata) {
@@ -236,7 +240,7 @@
   base::TimeTicks start = base::TimeTicks::Now();
 
   leveldb::Status status =
-      database_->Write(leveldb::WriteOptions(), &round_deletion_batch_);
+      database()->Write(leveldb::WriteOptions(), &round_deletion_batch_);
   round_deletion_batch_.Clear();
   has_writes_ = false;
 
@@ -291,7 +295,7 @@
     leveldb::ReadOptions iterator_options;
     iterator_options.fill_cache = false;
     iterator_options.verify_checksums = true;
-    iterator_.reset(database_->NewIterator(iterator_options));
+    iterator_.reset(database()->NewIterator(iterator_options));
   }
 
   if (!sweep_state_.database_it) {
@@ -412,7 +416,7 @@
 
     std::string exists_value;
     leveldb::Status s =
-        database_->Get(leveldb::ReadOptions(), exists_key, &exists_value);
+        database()->Get(leveldb::ReadOptions(), exists_key, &exists_value);
     if (!s.ok()) {
       ++metrics_.num_errors_reading_exists_table;
       iterator_->Next();
diff --git a/content/browser/indexed_db/indexed_db_tombstone_sweeper.h b/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
index d7a02e7..49c89e3 100644
--- a/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
+++ b/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
@@ -84,8 +84,10 @@
                             leveldb::DB* database);
   ~IndexedDBTombstoneSweeper() override;
 
+  bool RequiresMetadata() const override;
+
   void SetMetadata(
-      std::vector<blink::IndexedDBDatabaseMetadata> const* metadata) override;
+      const std::vector<blink::IndexedDBDatabaseMetadata>* metadata) override;
 
   void Stop(IndexedDBPreCloseTaskQueue::StopReason reason) override;
 
@@ -178,7 +180,6 @@
   const base::TickClock* clock_for_testing_ = nullptr;
   base::Optional<base::TimeTicks> start_time_;
 
-  leveldb::DB* database_ = nullptr;
   bool has_writes_ = false;
   leveldb::WriteBatch round_deletion_batch_;
   base::TimeDelta total_deletion_time_;
diff --git a/content/browser/loader/navigation_url_loader.cc b/content/browser/loader/navigation_url_loader.cc
index eee2a8c..7e82408 100644
--- a/content/browser/loader/navigation_url_loader.cc
+++ b/content/browser/loader/navigation_url_loader.cc
@@ -25,7 +25,7 @@
     StoragePartition* storage_partition,
     std::unique_ptr<NavigationRequestInfo> request_info,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
-    ServiceWorkerNavigationHandle* service_worker_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     AppCacheNavigationHandle* appcache_handle,
     scoped_refptr<PrefetchedSignedExchangeCache>
         prefetched_signed_exchange_cache,
diff --git a/content/browser/loader/navigation_url_loader.h b/content/browser/loader/navigation_url_loader.h
index dc26008..18e4859 100644
--- a/content/browser/loader/navigation_url_loader.h
+++ b/content/browser/loader/navigation_url_loader.h
@@ -27,7 +27,7 @@
 class NavigationURLLoaderDelegate;
 class NavigationURLLoaderFactory;
 class PrefetchedSignedExchangeCache;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class StoragePartition;
 struct NavigationRequestInfo;
 
@@ -53,7 +53,7 @@
       StoragePartition* storage_partition,
       std::unique_ptr<NavigationRequestInfo> request_info,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       AppCacheNavigationHandle* appcache_handle,
       scoped_refptr<PrefetchedSignedExchangeCache>
           prefetched_signed_exchange_cache,
diff --git a/content/browser/loader/navigation_url_loader_factory.h b/content/browser/loader/navigation_url_loader_factory.h
index 8d90dd343..55e248ee 100644
--- a/content/browser/loader/navigation_url_loader_factory.h
+++ b/content/browser/loader/navigation_url_loader_factory.h
@@ -20,7 +20,7 @@
       StoragePartition* storage_partition,
       std::unique_ptr<NavigationRequestInfo> request_info,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       NavigationURLLoaderDelegate* delegate,
       bool is_served_from_back_forward_cache) = 0;
 
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 92cceed..e26b5d7 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -37,8 +37,8 @@
 #include "content/browser/loader/single_request_url_loader_factory.h"
 #include "content/browser/navigation_subresource_loader_params.h"
 #include "content/browser/service_worker/service_worker_container_host.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_request_handler.h"
 #include "content/browser/storage_partition_impl.h"
@@ -410,10 +410,10 @@
   void Start(
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
           pending_network_loader_factory,
-      ServiceWorkerNavigationHandle*
-          service_worker_navigation_handle /* for UI thread only */,
-      ServiceWorkerNavigationHandleCore*
-          service_worker_navigation_handle_core /* for IO thread only */,
+      ServiceWorkerMainResourceHandle*
+          service_worker_handle /* for UI thread only */,
+      ServiceWorkerMainResourceHandleCore*
+          service_worker_handle_core /* for IO thread only */,
       AppCacheNavigationHandle* appcache_handle,
       scoped_refptr<PrefetchedSignedExchangeCache>
           prefetched_signed_exchange_cache,
@@ -434,7 +434,7 @@
     web_contents_getter_ = base::BindRepeating(
         &WebContents::FromFrameTreeNodeId, frame_tree_node_id_);
     navigation_ui_data_ = std::move(navigation_ui_data);
-    service_worker_navigation_handle_ = service_worker_navigation_handle;
+    service_worker_handle_ = service_worker_handle;
 
     base::PostTask(FROM_HERE, {BrowserThread::UI},
                    base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted,
@@ -515,11 +515,11 @@
     }
 
     // Set up an interceptor for service workers.
-    if (service_worker_navigation_handle_) {
+    if (service_worker_handle_) {
       std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
           ServiceWorkerRequestHandler::CreateForNavigation(
-              resource_request_->url,
-              service_worker_navigation_handle_->AsWeakPtr(), *request_info);
+              resource_request_->url, service_worker_handle_->AsWeakPtr(),
+              *request_info);
       // The interceptor may not be created in certain cases (e.g., the origin
       // is not secure).
       if (service_worker_interceptor)
@@ -1105,11 +1105,11 @@
           // Service Worker related APIs will fail with NoDocumentURL error.
           // TODO(crbug/898733): Support SignedExchange loading and Service
           // Worker integration.
-          if (service_worker_navigation_handle_) {
+          if (service_worker_handle_) {
             RunOrPostTaskOnThread(
                 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
                 base::BindOnce(
-                    [](ServiceWorkerNavigationHandleCore* core) {
+                    [](ServiceWorkerMainResourceHandleCore* core) {
                       base::WeakPtr<ServiceWorkerContainerHost> container_host =
                           core->container_host();
                       if (container_host) {
@@ -1122,8 +1122,7 @@
                     // Unretained() is safe because the handle owns the core,
                     // and core gets deleted on the core thread in a task that
                     // must occur after this task.
-                    base::Unretained(
-                        service_worker_navigation_handle_->core())));
+                    base::Unretained(service_worker_handle_->core())));
           }
         }
         return true;
@@ -1260,7 +1259,7 @@
   // Used to reset the state of ServiceWorkerProviderHost when
   // SignedExchangeRequestHandler will handle the response.
   base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
-  ServiceWorkerNavigationHandle* service_worker_navigation_handle_ = nullptr;
+  ServiceWorkerMainResourceHandle* service_worker_handle_ = nullptr;
 
   // Counts the time overhead of all the hops from the UI to the IO threads.
   base::TimeDelta ui_to_io_time_;
@@ -1283,7 +1282,7 @@
     StoragePartition* storage_partition,
     std::unique_ptr<NavigationRequestInfo> request_info,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
-    ServiceWorkerNavigationHandle* service_worker_navigation_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     AppCacheNavigationHandle* appcache_handle,
     scoped_refptr<PrefetchedSignedExchangeCache>
         prefetched_signed_exchange_cache,
@@ -1300,10 +1299,8 @@
       request_info->common_params->navigation_start, "FrameTreeNode id",
       frame_tree_node_id);
 
-  ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
-      service_worker_navigation_handle
-          ? service_worker_navigation_handle->core()
-          : nullptr;
+  ServiceWorkerMainResourceHandleCore* service_worker_handle_core =
+      service_worker_handle ? service_worker_handle->core() : nullptr;
 
   std::unique_ptr<network::ResourceRequest> new_request =
       CreateResourceRequest(request_info.get(), frame_tree_node_id);
@@ -1443,8 +1440,8 @@
       std::move(known_schemes), bypass_redirect_checks,
       weak_factory_.GetWeakPtr());
   request_controller_->Start(
-      std::move(pending_network_factory), service_worker_navigation_handle,
-      service_worker_navigation_handle_core, appcache_handle,
+      std::move(pending_network_factory), service_worker_handle,
+      service_worker_handle_core, appcache_handle,
       std::move(prefetched_signed_exchange_cache),
       std::move(signed_exchange_prefetch_metric_recorder),
       std::move(request_info), std::move(navigation_ui_data),
diff --git a/content/browser/loader/navigation_url_loader_impl.h b/content/browser/loader/navigation_url_loader_impl.h
index aeb14686..87a0909 100644
--- a/content/browser/loader/navigation_url_loader_impl.h
+++ b/content/browser/loader/navigation_url_loader_impl.h
@@ -42,7 +42,7 @@
       StoragePartition* storage_partition,
       std::unique_ptr<NavigationRequestInfo> request_info,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       AppCacheNavigationHandle* appcache_handle,
       scoped_refptr<PrefetchedSignedExchangeCache>
           prefetched_signed_exchange_cache,
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h
index de89d29..af7b324 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -31,7 +31,6 @@
 class BrowserCompositorMacClient {
  public:
   virtual SkColor BrowserCompositorMacGetGutterColor() const = 0;
-  virtual void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) = 0;
   virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
   virtual void DestroyCompositorForShutdown() = 0;
   virtual bool OnBrowserCompositorSurfaceIdChanged() = 0;
@@ -68,14 +67,9 @@
   // no valid frame is available.
   const gfx::CALayerParams* GetLastCALayerParams() const;
 
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack);
   void SetBackgroundColor(SkColor background_color);
   void UpdateVSyncParameters(const base::TimeTicks& timebase,
                              const base::TimeDelta& interval);
-  void SetNeedsBeginFrames(bool needs_begin_frames);
-  void SetWantsAnimateOnlyBeginFrames();
   void TakeFallbackContentFrom(BrowserCompositorMac* other);
 
   // Update the renderer's SurfaceId to reflect the current dimensions of the
@@ -88,6 +82,7 @@
   // Update the renderer's SurfaceId to reflect |new_size_in_pixels| in
   // anticipation of the NSView resizing during auto-resize.
   void UpdateSurfaceFromChild(
+      bool auto_resize_enabled,
       float new_device_scale_factor,
       const gfx::Size& new_size_in_pixels,
       const viz::LocalSurfaceIdAllocation& child_local_surface_id_allocation);
@@ -128,7 +123,6 @@
   ui::Layer* DelegatedFrameHostGetLayer() const override;
   bool DelegatedFrameHostIsVisible() const override;
   SkColor DelegatedFrameHostGetGutterColor() const override;
-  void OnBeginFrame(base::TimeTicks frame_time) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
   float GetDeviceScaleFactor() const override;
   void InvalidateLocalSurfaceIdOnEviction() override;
@@ -186,8 +180,6 @@
   std::unique_ptr<ui::Layer> root_layer_;
 
   SkColor background_color_ = SK_ColorWHITE;
-  viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
-      nullptr;
 
   // The viz::ParentLocalSurfaceIdAllocator for the delegated frame host
   // dispenses viz::LocalSurfaceIds that are renderered into by the renderer
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index e291192f..c1593171 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -108,17 +108,6 @@
   return viz::FrameSinkId();
 }
 
-void BrowserCompositorMac::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
-  delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
-      renderer_compositor_frame_sink_);
-}
-
-void BrowserCompositorMac::OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {
-  delegated_frame_host_->DidNotProduceFrame(ack);
-}
-
 void BrowserCompositorMac::SetBackgroundColor(SkColor background_color) {
   background_color_ = background_color;
   if (recyclable_compositor_)
@@ -161,20 +150,23 @@
 }
 
 void BrowserCompositorMac::UpdateSurfaceFromChild(
+    bool auto_resize_enabled,
     float new_device_scale_factor,
     const gfx::Size& new_size_in_pixels,
     const viz::LocalSurfaceIdAllocation& child_local_surface_id_allocation) {
   if (dfh_local_surface_id_allocator_.UpdateFromChild(
           child_local_surface_id_allocation)) {
-    dfh_display_.set_device_scale_factor(new_device_scale_factor);
-    dfh_size_dip_ = gfx::ConvertSizeToDIP(dfh_display_.device_scale_factor(),
-                                          new_size_in_pixels);
-    dfh_size_pixels_ = new_size_in_pixels;
-    root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
-    if (recyclable_compositor_) {
-      recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
-                                            dfh_display_.device_scale_factor(),
-                                            dfh_display_.color_space());
+    if (auto_resize_enabled) {
+      dfh_display_.set_device_scale_factor(new_device_scale_factor);
+      dfh_size_dip_ = gfx::ConvertSizeToDIP(dfh_display_.device_scale_factor(),
+                                            new_size_in_pixels);
+      dfh_size_pixels_ = new_size_in_pixels;
+      root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
+      if (recyclable_compositor_) {
+        recyclable_compositor_->UpdateSurface(
+            dfh_size_pixels_, dfh_display_.device_scale_factor(),
+            dfh_display_.color_space());
+      }
     }
     delegated_frame_host_->EmbedSurface(
         dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
@@ -310,14 +302,6 @@
   ui::RecyclableCompositorMacFactory::Get()->DisableRecyclingForShutdown();
 }
 
-void BrowserCompositorMac::SetNeedsBeginFrames(bool needs_begin_frames) {
-  delegated_frame_host_->SetNeedsBeginFrames(needs_begin_frames);
-}
-
-void BrowserCompositorMac::SetWantsAnimateOnlyBeginFrames() {
-  delegated_frame_host_->SetWantsAnimateOnlyBeginFrames();
-}
-
 void BrowserCompositorMac::TakeFallbackContentFrom(
     BrowserCompositorMac* other) {
   delegated_frame_host_->TakeFallbackContentFrom(
@@ -339,10 +323,6 @@
   return client_->BrowserCompositorMacGetGutterColor();
 }
 
-void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) {
-  client_->BrowserCompositorMacOnBeginFrame(frame_time);
-}
-
 void BrowserCompositorMac::OnFrameTokenChanged(uint32_t frame_token) {
   client_->OnFrameTokenChanged(frame_token);
 }
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index c12f354f..05346d61 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -20,10 +20,6 @@
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/resources/single_release_callback.h"
-#include "components/viz/common/switches.h"
-#include "components/viz/host/host_frame_sink_manager.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
-#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/public/common/content_switches.h"
@@ -49,12 +45,9 @@
                                        bool should_register_frame_sink_id)
     : frame_sink_id_(frame_sink_id),
       client_(client),
-      enable_viz_(features::IsVizDisplayCompositorEnabled()),
       should_register_frame_sink_id_(should_register_frame_sink_id),
       host_frame_sink_manager_(GetHostFrameSinkManager()),
       frame_evictor_(std::make_unique<viz::FrameEvictor>(this)) {
-  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  factory->GetContextFactory()->AddObserver(this);
   DCHECK(host_frame_sink_manager_);
   host_frame_sink_manager_->RegisterFrameSinkId(
       frame_sink_id_, this, viz::ReportFirstSurfaceActivation::kNo);
@@ -62,7 +55,6 @@
       frame_sink_id_, "Compositing.MainFrameSynchronization.Duration");
   host_frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id_,
                                                    "DelegatedFrameHost");
-  CreateCompositorFrameSinkSupport();
   frame_evictor_->SetVisible(client_->DelegatedFrameHostIsVisible());
 
   stale_content_layer_ =
@@ -73,10 +65,7 @@
 
 DelegatedFrameHost::~DelegatedFrameHost() {
   DCHECK(!compositor_);
-  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  factory->GetContextFactory()->RemoveObserver(this);
 
-  ResetCompositorFrameSinkSupport();
   DCHECK(host_frame_sink_manager_);
   host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
@@ -209,35 +198,6 @@
   return local_surface_id_.is_valid();
 }
 
-void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
-  if (enable_viz_) {
-    NOTIMPLEMENTED();
-    return;
-  }
-
-  needs_begin_frame_ = needs_begin_frames;
-  support_->SetNeedsBeginFrame(needs_begin_frames);
-}
-
-void DelegatedFrameHost::SetWantsAnimateOnlyBeginFrames() {
-  if (enable_viz_) {
-    NOTIMPLEMENTED();
-    return;
-  }
-
-  support_->SetWantsAnimateOnlyBeginFrames();
-}
-
-void DelegatedFrameHost::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
-  if (enable_viz_) {
-    NOTIMPLEMENTED();
-    return;
-  }
-
-  DCHECK(!ack.has_damage);
-  support_->DidNotProduceFrame(ack);
-}
-
 bool DelegatedFrameHost::HasPrimarySurface() const {
   const viz::SurfaceId* primary_surface_id =
       client_->DelegatedFrameHostGetLayer()->GetSurfaceId();
@@ -314,36 +274,6 @@
   return client_->DelegatedFrameHostGetGutterColor();
 }
 
-void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  ResetCompositorFrameSinkSupport();
-  renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
-  CreateCompositorFrameSinkSupport();
-}
-
-void DelegatedFrameHost::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                  std::move(hit_test_region_list));
-}
-
-void DelegatedFrameHost::DidReceiveCompositorFrameAck(
-    const std::vector<viz::ReturnedResource>& resources) {
-  renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-}
-
-void DelegatedFrameHost::ReclaimResources(
-    const std::vector<viz::ReturnedResource>& resources) {
-  renderer_compositor_frame_sink_->ReclaimResources(resources);
-}
-
-void DelegatedFrameHost::OnBeginFramePausedChanged(bool paused) {
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
-}
-
 void DelegatedFrameHost::OnFirstSurfaceActivation(
     const viz::SurfaceInfo& surface_info) {
   NOTREACHED();
@@ -353,14 +283,6 @@
   client_->OnFrameTokenChanged(frame_token);
 }
 
-void DelegatedFrameHost::OnBeginFrame(
-    const viz::BeginFrameArgs& args,
-    const viz::FrameTimingDetailsMap& timing_details) {
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->OnBeginFrame(args, timing_details);
-  client_->OnBeginFrame(args.frame_time);
-}
-
 void DelegatedFrameHost::ResetFallbackToFirstNavigationSurface() {
   const viz::SurfaceId* fallback_surface_id =
       client_->DelegatedFrameHostGetLayer()->GetOldestAcceptableFallback();
@@ -479,11 +401,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, ContextFactoryObserver implementation:
-
-void DelegatedFrameHost::OnLostSharedContext() {}
-
-////////////////////////////////////////////////////////////////////////////////
 // DelegatedFrameHost, private:
 
 void DelegatedFrameHost::AttachToCompositor(ui::Compositor* compositor) {
@@ -506,29 +423,6 @@
   compositor_ = nullptr;
 }
 
-void DelegatedFrameHost::CreateCompositorFrameSinkSupport() {
-  if (enable_viz_)
-    return;
-
-  DCHECK(!support_);
-  constexpr bool is_root = false;
-  DCHECK(host_frame_sink_manager_);
-  support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
-      this, frame_sink_id_, is_root);
-  if (compositor_ && should_register_frame_sink_id_)
-    compositor_->AddChildFrameSink(frame_sink_id_);
-  if (needs_begin_frame_)
-    support_->SetNeedsBeginFrame(true);
-}
-
-void DelegatedFrameHost::ResetCompositorFrameSinkSupport() {
-  if (!support_)
-    return;
-  if (compositor_ && should_register_frame_sink_id_)
-    compositor_->RemoveChildFrameSink(frame_sink_id_);
-  support_.reset();
-}
-
 void DelegatedFrameHost::DidNavigate() {
   first_local_surface_id_after_navigation_ = local_surface_id_;
 }
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index f1dc584..a1f5ea0 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -19,7 +19,6 @@
 #include "components/viz/host/hit_test/hit_test_query.h"
 #include "components/viz/host/host_frame_sink_client.h"
 #include "components/viz/host/host_frame_sink_manager.h"
-#include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/renderer_host/dip_util.h"
 #include "content/common/content_export.h"
 #include "content/common/tab_switch_time_recorder.h"
@@ -31,10 +30,6 @@
 #include "ui/events/event.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
-namespace viz {
-class CompositorFrameSinkSupport;
-}
-
 namespace content {
 
 class DelegatedFrameHost;
@@ -50,7 +45,6 @@
   virtual bool DelegatedFrameHostIsVisible() const = 0;
   // Returns the color that the resize gutters should be drawn with.
   virtual SkColor DelegatedFrameHostGetGutterColor() const = 0;
-  virtual void OnBeginFrame(base::TimeTicks frame_time) = 0;
   virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
   virtual float GetDeviceScaleFactor() const = 0;
   virtual void InvalidateLocalSurfaceIdOnEviction() = 0;
@@ -64,9 +58,7 @@
 // the ui::Compositor associated with its DelegatedFrameHostClient.
 class CONTENT_EXPORT DelegatedFrameHost
     : public ui::CompositorObserver,
-      public ui::ContextFactoryObserver,
       public viz::FrameEvictorClient,
-      public viz::mojom::CompositorFrameSinkClient,
       public viz::HostFrameSinkClient {
  public:
   enum class FrameEvictionState {
@@ -97,33 +89,14 @@
   // ui::CompositorObserver implementation.
   void OnCompositingShuttingDown(ui::Compositor* compositor) override;
 
-  // ui::ContextFactoryObserver implementation.
-  void OnLostSharedContext() override;
-
   void ResetFallbackToFirstNavigationSurface();
 
-  // viz::mojom::CompositorFrameSinkClient implementation.
-  void DidReceiveCompositorFrameAck(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFrame(const viz::BeginFrameArgs& args,
-                    const viz::FrameTimingDetailsMap& timing_details) override;
-  void ReclaimResources(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFramePausedChanged(bool paused) override;
-
   // viz::HostFrameSinkClient implementation.
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
 
   // Public interface exposed to RenderWidgetHostView.
 
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list);
-
   // kOccluded means the native window for the host was
   // occluded/hidden, kOther is for other causes, e.g., a tab became a
   // background tab.
@@ -161,17 +134,10 @@
   bool CanCopyFromCompositingSurface() const;
   const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
 
-  void SetNeedsBeginFrames(bool needs_begin_frames);
-  void SetWantsAnimateOnlyBeginFrames();
-  void DidNotProduceFrame(const viz::BeginFrameAck& ack);
-
   // Returns the surface id for the most recently embedded surface.
   viz::SurfaceId GetCurrentSurfaceId() const {
     return viz::SurfaceId(frame_sink_id_, local_surface_id_);
   }
-  viz::CompositorFrameSinkSupport* GetCompositorFrameSinkSupportForTesting() {
-    return support_.get();
-  }
 
   bool HasPrimarySurface() const;
   bool HasFallbackSurface() const;
@@ -236,7 +202,6 @@
 
   const viz::FrameSinkId frame_sink_id_;
   DelegatedFrameHostClient* const client_;
-  const bool enable_viz_;
   const bool should_register_frame_sink_id_;
   ui::Compositor* compositor_ = nullptr;
 
@@ -253,14 +218,6 @@
 
   viz::HostFrameSinkManager* const host_frame_sink_manager_;
 
-  // State for rendering into a Surface.
-  std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
-
-  bool needs_begin_frame_ = false;
-
-  viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
-      nullptr;
-
   std::unique_ptr<viz::FrameEvictor> frame_evictor_;
 
   viz::LocalSurfaceId first_local_surface_id_after_navigation_;
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/content/browser/renderer_host/delegated_frame_host_client_aura.cc
index f002a3c9..273c920 100644
--- a/content/browser/renderer_host/delegated_frame_host_client_aura.cc
+++ b/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -43,10 +43,6 @@
   return SK_ColorWHITE;
 }
 
-void DelegatedFrameHostClientAura::OnBeginFrame(base::TimeTicks frame_time) {
-  render_widget_host_view_->OnBeginFrame(frame_time);
-}
-
 void DelegatedFrameHostClientAura::OnFrameTokenChanged(uint32_t frame_token) {
   render_widget_host_view_->OnFrameTokenChangedForView(frame_token);
 }
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.h b/content/browser/renderer_host/delegated_frame_host_client_aura.h
index e7c62fb..dc80767 100644
--- a/content/browser/renderer_host/delegated_frame_host_client_aura.h
+++ b/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -30,7 +30,6 @@
   ui::Layer* DelegatedFrameHostGetLayer() const override;
   bool DelegatedFrameHostIsVisible() const override;
   SkColor DelegatedFrameHostGetGutterColor() const override;
-  void OnBeginFrame(base::TimeTicks frame_time) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
   float GetDeviceScaleFactor() const override;
   void InvalidateLocalSurfaceIdOnEviction() override;
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 4b3e151..44c32d2 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -66,7 +66,8 @@
         latency_info.ScaledBy(scale));
   }
 
-  return std::make_unique<InputEvent>(event.Clone(), latency_info);
+  return std::make_unique<InputEvent>(ui::WebInputEventTraits::Clone(event),
+                                      latency_info);
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 3544098..1ce9b56 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -203,7 +203,6 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "net/url_request/url_request_context_getter.h"
-#include "ppapi/buildflags/buildflags.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "services/device/public/mojom/power_monitor.mojom.h"
 #include "services/device/public/mojom/screen_orientation.mojom.h"
@@ -1546,8 +1545,6 @@
       /* render_frame_id= */ ChildProcessHost::kInvalidUniqueID,
       storage_partition_impl_->GetServiceWorkerContext()));
 
-  AddObserver(indexed_db_factory_.get());
-
   InitializeChannelProxy();
 
   const int id = GetID();
@@ -2131,39 +2128,35 @@
       registry.get(),
       base::BindRepeating(
           &RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider,
-          base::Unretained(this)));
+          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::BindFrameSinkProvider,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::BindCompositingModeReporter,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
-      base::BindRepeating(
-          &BackgroundSyncContextImpl::CreateOneShotSyncService,
-          base::Unretained(
-              storage_partition_impl_->GetBackgroundSyncContext())));
+      base::BindRepeating(&RenderProcessHostImpl::CreateOneShotSyncService,
+                          weak_factory_.GetWeakPtr()));
   AddUIThreadInterface(
       registry.get(),
-      base::BindRepeating(
-          &BackgroundSyncContextImpl::CreatePeriodicSyncService,
-          base::Unretained(
-              storage_partition_impl_->GetBackgroundSyncContext())));
+      base::BindRepeating(&RenderProcessHostImpl::CreatePeriodicSyncService,
+                          weak_factory_.GetWeakPtr()));
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::CreateStoragePartitionService,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(
           &RenderProcessHostImpl::CreateBroadcastChannelProvider,
-          base::Unretained(this)));
+          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(registry.get(),
                        base::BindRepeating(&ClipboardHostImpl::Create));
@@ -2171,15 +2164,17 @@
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::BindWebDatabaseHostImpl,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(
-          [](RenderProcessHostImpl* host,
+          [](base::WeakPtr<RenderProcessHostImpl> host,
              mojo::PendingReceiver<
                  memory_instrumentation::mojom::CoordinatorConnector>
                  receiver) {
+            if (!host)
+              return;
             host->coordinator_connector_receiver_.reset();
             host->coordinator_connector_receiver_.Bind(std::move(receiver));
             if (!host->GetProcess().IsValid()) {
@@ -2188,7 +2183,7 @@
               host->coordinator_connector_receiver_.Pause();
             }
           },
-          base::Unretained(this)));
+          weak_factory_.GetWeakPtr()));
 
   registry->AddInterface(base::BindRepeating(&MimeRegistryImpl::Create),
                          base::CreateSequencedTaskRunner(
@@ -2222,8 +2217,8 @@
   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
     AddUIThreadInterface(
         registry.get(),
-        base::BindRepeating(&PushMessagingManager::AddPushMessagingReceiver,
-                            base::Unretained(push_messaging_manager_.get())));
+        base::BindRepeating(&RenderProcessHostImpl::BindPushMessagingManager,
+                            weak_factory_.GetWeakPtr()));
   } else {
     registry->AddInterface(
         base::BindRepeating(&PushMessagingManager::AddPushMessagingReceiver,
@@ -2272,7 +2267,7 @@
       registry.get(),
       base::BindRepeating(
           &RenderProcessHostImpl::CreateAgentMetricsCollectorHost,
-          base::Unretained(this)));
+          weak_factory_.GetWeakPtr()));
 
   registry->AddInterface(
       base::BindRepeating(&metrics::CreateSingleSampleMetricsProvider));
@@ -2280,12 +2275,12 @@
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::BindPeerConnectionTrackerHost,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::CreateCodeCacheHost,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
 #if BUILDFLAG(ENABLE_REPORTING)
   AddUIThreadInterface(
@@ -2295,14 +2290,14 @@
 
   AddUIThreadInterface(
       registry.get(),
-      base::BindRepeating(&P2PSocketDispatcherHost::BindReceiver,
-                          base::Unretained(p2p_socket_dispatcher_host_.get())));
+      base::BindRepeating(&RenderProcessHostImpl::BindP2PSocketManager,
+                          weak_factory_.GetWeakPtr()));
 
 #if BUILDFLAG(ENABLE_MDNS)
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::CreateMdnsResponder,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 #endif  // BUILDFLAG(ENABLE_MDNS)
 
   AddUIThreadInterface(registry.get(),
@@ -2321,7 +2316,7 @@
       registry.get(),
       base::BindRepeating(
           &RenderProcessHostImpl::CreateURLLoaderFactoryForRendererProcess,
-          base::Unretained(this)));
+          weak_factory_.GetWeakPtr()));
 
   registry->AddInterface(
       base::BindRepeating(&BlobRegistryWrapper::Bind,
@@ -2335,8 +2330,8 @@
   }
   AddUIThreadInterface(
       registry.get(),
-      base::BindRepeating(&PluginRegistryImpl::Bind,
-                          base::Unretained(plugin_registry_.get())));
+      base::BindRepeating(&RenderProcessHostImpl::BindPluginRegistry,
+                          weak_factory_.GetWeakPtr()));
 #endif
 
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
@@ -2346,12 +2341,12 @@
   AddUIThreadInterface(
       registry.get(),
       base::BindRepeating(&RenderProcessHostImpl::BindVideoDecoderService,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 
   AddUIThreadInterface(
       registry.get(),
-      base::BindRepeating(&AecDumpManagerImpl::AddReceiver,
-                          base::Unretained(&aec_dump_manager_)));
+      base::BindRepeating(&RenderProcessHostImpl::BindAecDumpManager,
+                          weak_factory_.GetWeakPtr()));
 
   // ---- Please do not register interfaces below this line ------
   //
@@ -2479,6 +2474,41 @@
       base::BindOnce(&WebDatabaseHostImpl::Create, GetID(),
                      base::WrapRefCounted(db_tracker), std::move(receiver)));
 }
+void RenderProcessHostImpl::BindAecDumpManager(
+    mojo::PendingReceiver<blink::mojom::AecDumpManager> receiver) {
+  aec_dump_manager_.AddReceiver(std::move(receiver));
+}
+
+void RenderProcessHostImpl::CreateOneShotSyncService(
+    mojo::PendingReceiver<blink::mojom::OneShotBackgroundSyncService>
+        receiver) {
+  storage_partition_impl_->GetBackgroundSyncContext()->CreateOneShotSyncService(
+      std::move(receiver));
+}
+
+void RenderProcessHostImpl::CreatePeriodicSyncService(
+    mojo::PendingReceiver<blink::mojom::PeriodicBackgroundSyncService>
+        receiver) {
+  storage_partition_impl_->GetBackgroundSyncContext()
+      ->CreatePeriodicSyncService(std::move(receiver));
+}
+
+void RenderProcessHostImpl::BindPushMessagingManager(
+    mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) {
+  push_messaging_manager_->AddPushMessagingReceiver(std::move(receiver));
+}
+
+void RenderProcessHostImpl::BindP2PSocketManager(
+    mojo::PendingReceiver<network::mojom::P2PSocketManager> receiver) {
+  p2p_socket_dispatcher_host_->BindReceiver(std::move(receiver));
+}
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+void RenderProcessHostImpl::BindPluginRegistry(
+    mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver) {
+  plugin_registry_->Bind(std::move(receiver));
+}
+#endif
 
 void RenderProcessHostImpl::RegisterCoordinatorClient(
     mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index fa147f8..d81f691 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -62,8 +62,10 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/invitation.h"
 #include "net/base/network_isolation_key.h"
+#include "ppapi/buildflags/buildflags.h"
 #include "services/device/public/mojom/battery_monitor.mojom-forward.h"
 #include "services/network/public/mojom/mdns_responder.mojom.h"
+#include "services/network/public/mojom/p2p.mojom-forward.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -73,6 +75,7 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/mojom/agents/agent_metrics.mojom.h"
 #include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
+#include "third_party/blink/public/mojom/background_sync/background_sync.mojom-forward.h"
 #include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h"
 #include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
 #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
@@ -80,6 +83,8 @@
 #include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
 #include "third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom.h"
+#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-forward.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-forward.h"
 #include "third_party/blink/public/mojom/webdatabase/web_database.mojom.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 
@@ -727,6 +732,22 @@
       mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver);
   void BindWebDatabaseHostImpl(
       mojo::PendingReceiver<blink::mojom::WebDatabaseHost> receiver);
+  void BindAecDumpManager(
+      mojo::PendingReceiver<blink::mojom::AecDumpManager> receiver);
+  void CreateOneShotSyncService(
+      mojo::PendingReceiver<blink::mojom::OneShotBackgroundSyncService>
+          receiver);
+  void CreatePeriodicSyncService(
+      mojo::PendingReceiver<blink::mojom::PeriodicBackgroundSyncService>
+          receiver);
+  void BindPushMessagingManager(
+      mojo::PendingReceiver<blink::mojom::PushMessaging> receiver);
+  void BindP2PSocketManager(
+      mojo::PendingReceiver<network::mojom::P2PSocketManager> receiver);
+#if BUILDFLAG(ENABLE_PLUGINS)
+  void BindPluginRegistry(
+      mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver);
+#endif
 
   // memory_instrumentation::mojom::CoordinatorConnector implementation:
   void RegisterCoordinatorClient(
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 38f1ec87..5080738 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -450,10 +450,6 @@
       if (!create_frame_sink_callback_.is_null())
         std::move(create_frame_sink_callback_).Run(view_->GetFrameSinkId());
     } else {
-      if (renderer_compositor_frame_sink_.is_bound()) {
-        view->DidCreateNewRendererCompositorFrameSink(
-            renderer_compositor_frame_sink_.get());
-      }
       // Views start out not needing begin frames, so only update its state
       // if the value has changed.
       if (needs_begin_frames_)
@@ -2949,16 +2945,6 @@
   compositor_frame_sink_receiver_.Bind(
       std::move(compositor_frame_sink_receiver),
       BrowserMainLoop::GetInstance()->GetResizeTaskRunner());
-
-  renderer_compositor_frame_sink_.reset();
-  renderer_compositor_frame_sink_.Bind(std::move(compositor_frame_sink_client));
-  auto* compositor_frame_sink_client_ptr =
-      renderer_compositor_frame_sink_.get();
-
-  if (view_) {
-    view_->DidCreateNewRendererCompositorFrameSink(
-        compositor_frame_sink_client_ptr);
-  }
 }
 
 void RenderWidgetHostImpl::RegisterRenderFrameMetadataObserver(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 1e606ff..f32d86f93 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1055,11 +1055,6 @@
          host()->delegate()->GetInputEventRouter();
 }
 
-void RenderWidgetHostViewAndroid::DidReceiveCompositorFrameAck(
-    const std::vector<viz::ReturnedResource>& resources) {
-  renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-}
-
 void RenderWidgetHostViewAndroid::DidPresentCompositorFrames(
     const viz::FrameTimingDetailsMap& timing_details) {
   timing_details_ = timing_details;
@@ -1067,25 +1062,6 @@
     AddBeginFrameRequest(BEGIN_FRAME);
 }
 
-void RenderWidgetHostViewAndroid::ReclaimResources(
-    const std::vector<viz::ReturnedResource>& resources) {
-  renderer_compositor_frame_sink_->ReclaimResources(resources);
-}
-
-void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  if (!delegated_frame_host_) {
-    DCHECK(!using_browser_compositor_);
-    // We don't expect RendererCompositorFrameSink on Android WebView.
-    // (crbug.com/721102)
-    bad_message::ReceivedBadMessage(host()->GetProcess(),
-                                    bad_message::RWH_BAD_FRAME_SINK_REQUEST);
-    return;
-  }
-  delegated_frame_host_->CompositorFrameSinkChanged();
-  renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
-}
-
 void RenderWidgetHostViewAndroid::EvictFrameIfNecessary() {
   if (!host()->delegate()->IsFullscreenForCurrentTab() ||
       current_surface_size_ == view_.GetPhysicalBackingSize()) {
@@ -1589,8 +1565,6 @@
   if (sync_compositor_) {
     sync_compositor_->BeginFrame(view_.GetWindowAndroid(), args,
                                  timing_details_);
-  } else if (renderer_compositor_frame_sink_) {
-    renderer_compositor_frame_sink_->OnBeginFrame(args, timing_details_);
   }
   timing_details_.clear();
 }
@@ -2237,8 +2211,6 @@
   if (!using_browser_compositor_ && !using_viz_for_webview_) {
     if (sync_compositor_)
       sync_compositor_->SetBeginFramePaused(paused);
-  } else if (renderer_compositor_frame_sink_) {
-    renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
   }
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 0812ec9..4c80fbc 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -152,9 +152,6 @@
       bool for_root_frame) override;
   bool LockMouse(bool request_unadjusted_movement) override;
   void UnlockMouse() override;
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
-      override;
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
@@ -245,9 +242,6 @@
   void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source);
   void DidPresentCompositorFrames(
       const viz::FrameTimingDetailsMap& timing_details);
-  void DidReceiveCompositorFrameAck(
-      const std::vector<viz::ReturnedResource>& resources);
-  void ReclaimResources(const std::vector<viz::ReturnedResource>& resources);
 
   // viz::BeginFrameObserver implementation.
   void OnBeginFrame(const viz::BeginFrameArgs& args) override;
@@ -566,9 +560,6 @@
   gfx::Point prev_mousedown_point_;
   int left_click_count_ = 0;
 
-  viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
-      nullptr;
-
   base::ObserverList<DestructionObserver>::Unchecked destruction_observers_;
 
   MouseWheelPhaseHandler mouse_wheel_phase_handler_;
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 fbad676f..322ccfe 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -363,7 +363,6 @@
       popup_child_host_view_(nullptr),
       is_loading_(false),
       has_composition_text_(false),
-      needs_begin_frames_(false),
       added_frame_observer_(false),
       cursor_visibility_state_in_renderer_(UNKNOWN),
 #if defined(OS_WIN)
@@ -573,21 +572,6 @@
   return this;
 }
 
-void RenderWidgetHostViewAura::SetNeedsBeginFrames(bool needs_begin_frames) {
-  needs_begin_frames_ = needs_begin_frames;
-  UpdateNeedsBeginFramesInternal();
-}
-
-void RenderWidgetHostViewAura::SetWantsAnimateOnlyBeginFrames() {
-  if (delegated_frame_host_)
-    delegated_frame_host_->SetWantsAnimateOnlyBeginFrames();
-}
-
-void RenderWidgetHostViewAura::OnBeginFrame(base::TimeTicks frame_time) {
-  host()->ProgressFlingIfNeeded(frame_time);
-  UpdateNeedsBeginFramesInternal();
-}
-
 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() const {
   RenderWidgetHostOwnerDelegate* owner_delegate = host()->owner_delegate();
   // TODO(crbug.com/689777): Child local roots do not work here?
@@ -882,30 +866,16 @@
 }
 #endif
 
-void RenderWidgetHostViewAura::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
-  if (delegated_frame_host_) {
-    delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
-        renderer_compositor_frame_sink_);
-  }
-}
-
 void RenderWidgetHostViewAura::SubmitCompositorFrame(
     const viz::LocalSurfaceId& local_surface_id,
     viz::CompositorFrame frame,
     base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  DCHECK(delegated_frame_host_);
-  TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
-
-  delegated_frame_host_->SubmitCompositorFrame(
-      local_surface_id, std::move(frame), std::move(hit_test_region_list));
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewAura::OnDidNotProduceFrame(
     const viz::BeginFrameAck& ack) {
-  if (delegated_frame_host_)
-    delegated_frame_host_->DidNotProduceFrame(ack);
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewAura::ResetFallbackToFirstNavigationSurface() {
@@ -2534,12 +2504,6 @@
       popup_child_host_view ? popup_child_host_view->event_handler() : nullptr);
 }
 
-void RenderWidgetHostViewAura::UpdateNeedsBeginFramesInternal() {
-  if (!delegated_frame_host_)
-    return;
-  delegated_frame_host_->SetNeedsBeginFrames(needs_begin_frames_);
-}
-
 void RenderWidgetHostViewAura::ScrollFocusedEditableNodeIntoRect(
     const gfx::Rect& node_rect) {
   RenderFrameHostImpl* rfh = GetFocusedFrame();
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 661541b..17ac9191 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -107,8 +107,8 @@
   bool IsMouseLocked() override;
   gfx::Size GetVisibleViewportSize() override;
   void SetInsets(const gfx::Insets& insets) override;
-  void SetNeedsBeginFrames(bool needs_begin_frames) override;
-  void SetWantsAnimateOnlyBeginFrames() override;
+  void SetNeedsBeginFrames(bool needs_begin_frames) override {}
+  void SetWantsAnimateOnlyBeginFrames() override {}
   TouchSelectionControllerClientManager*
   GetTouchSelectionControllerClientManager() override;
 
@@ -158,9 +158,6 @@
   void UnlockKeyboard() override;
   bool IsKeyboardLocked() override;
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
-      override;
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
@@ -523,8 +520,6 @@
   void OnTextSelectionChanged(TextInputManager* text_input_mangager,
                               RenderWidgetHostViewBase* updated_view) override;
 
-  void OnBeginFrame(base::TimeTicks frame_time);
-
   // Detaches |this| from the input method object.
   void DetachFromInputMethod();
 
@@ -548,9 +543,6 @@
   // and to notify the |event_handler_|.
   void SetPopupChild(RenderWidgetHostViewAura* popup_child_host_view);
 
-  // Tells DelegatedFrameHost whether we need to receive BeginFrames.
-  void UpdateNeedsBeginFramesInternal();
-
   // Called when the window title is changed.
   void WindowTitleChanged();
 
@@ -602,9 +594,6 @@
   // Current tooltip text.
   base::string16 tooltip_;
 
-  // Whether a request for begin frames has been issued.
-  bool needs_begin_frames_;
-
   // Whether or not a frame observer has been added.
   bool added_frame_observer_;
 
@@ -657,9 +646,6 @@
 
   float device_scale_factor_;
 
-  viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
-      nullptr;
-
   // While this is a ui::EventHandler for targetting, |event_handler_| actually
   // provides an implementation, and directs events to |host_|.
   std::unique_ptr<RenderWidgetHostViewEventHandler> event_handler_;
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 5ee299a3..764618c 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
@@ -248,25 +248,10 @@
             new FakeDelegatedFrameHostClientAura(this)) {
     InstallDelegatedFrameHostClient(
         this, base::WrapUnique(delegated_frame_host_client_));
-    CreateNewRendererCompositorFrameSink();
   }
 
   ~FakeRenderWidgetHostViewAura() override {}
 
-  void CreateNewRendererCompositorFrameSink() {
-    mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink;
-    mojo::PendingReceiver<viz::mojom::CompositorFrameSink> sink_receiver =
-        sink.InitWithNewPipeAndPassReceiver();
-
-    renderer_compositor_frame_sink_remote_.reset();
-    renderer_compositor_frame_sink_ =
-        std::make_unique<FakeRendererCompositorFrameSink>(
-            std::move(sink), renderer_compositor_frame_sink_remote_
-                                 .BindNewPipeAndPassReceiver());
-    DidCreateNewRendererCompositorFrameSink(
-        renderer_compositor_frame_sink_remote_.get());
-  }
-
   void UseFakeDispatcher() {
     dispatcher_ = new FakeWindowEventDispatcher(window()->GetHost());
     std::unique_ptr<aura::WindowEventDispatcher> dispatcher(dispatcher_);
@@ -294,10 +279,6 @@
     return GetDelegatedFrameHost()->HasSavedFrame();
   }
 
-  void ReclaimResources(const std::vector<viz::ReturnedResource>& resources) {
-    GetDelegatedFrameHost()->ReclaimResources(resources);
-  }
-
   const ui::MotionEventAura& pointer_state() {
     return event_handler()->pointer_state();
   }
@@ -309,8 +290,6 @@
 
   gfx::Size last_frame_size_;
   FakeWindowEventDispatcher* dispatcher_;
-  std::unique_ptr<FakeRendererCompositorFrameSink>
-      renderer_compositor_frame_sink_;
 
  private:
   FakeDelegatedFrameHostClientAura* delegated_frame_host_client_;
@@ -594,15 +573,6 @@
     events.clear();
   }
 
-  // TODO(crbug.com/844469): Delete this helper once Viz launches as it will be
-  // obsolete.
-  viz::FrameSinkManagerImpl* GetFrameSinkManager() {
-    DCHECK(!features::IsVizDisplayCompositorEnabled());
-    return view_->GetDelegatedFrameHost()
-        ->GetCompositorFrameSinkSupportForTesting()
-        ->frame_sink_manager();
-  }
-
   const ui::MotionEventAura& pointer_state() { return view_->pointer_state(); }
 
  protected:
@@ -1549,13 +1519,13 @@
   base::RunLoop().RunUntilIdle();
   auto events = GetAndResetDispatchedMessages();
   ASSERT_FALSE(events.empty());
-  const NativeWebKeyboardEvent* native_key_event1 =
-      static_cast<const NativeWebKeyboardEvent*>(
+  const blink::WebKeyboardEvent* blink_key_event1 =
+      static_cast<const blink::WebKeyboardEvent*>(
           events[0]->ToEvent()->Event()->web_event.get());
-  ASSERT_TRUE(native_key_event1);
-  ASSERT_EQ(key_event1.key_code(), native_key_event1->windows_key_code);
+  ASSERT_TRUE(blink_key_event1);
+  ASSERT_EQ(key_event1.key_code(), blink_key_event1->windows_key_code);
   ASSERT_EQ(ui::KeycodeConverter::DomCodeToNativeKeycode(key_event1.code()),
-            native_key_event1->native_key_code);
+            blink_key_event1->native_key_code);
 
   // These keys will pass through the prehandler since they aren't locked.
   std::vector<ui::DomCode> dom_codes = {
@@ -1651,15 +1621,15 @@
     ASSERT_FALSE(events.empty())
         << "Failed for DomCode: "
         << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
-    const NativeWebKeyboardEvent* native_key_event =
-        static_cast<const NativeWebKeyboardEvent*>(
+    const blink::WebKeyboardEvent* blink_key_event =
+        static_cast<const blink::WebKeyboardEvent*>(
             events[0]->ToEvent()->Event()->web_event.get());
-    ASSERT_TRUE(native_key_event)
+    ASSERT_TRUE(blink_key_event)
         << "Failed for DomCode: "
         << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
-    ASSERT_EQ(key_event.key_code(), native_key_event->windows_key_code);
+    ASSERT_EQ(key_event.key_code(), blink_key_event->windows_key_code);
     ASSERT_EQ(ui::KeycodeConverter::DomCodeToNativeKeycode(key_event.code()),
-              native_key_event->native_key_code);
+              blink_key_event->native_key_code);
   }
 
   // Although this key was locked, it will still pass through the prehandler as
@@ -3028,82 +2998,6 @@
   return frame;
 }
 
-// This test verifies that returned resources do not require a pending ack.
-TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
-  gfx::Size view_size(100, 100);
-  gfx::Rect view_rect(view_size);
-
-  view_->InitAsChild(nullptr);
-  aura::client::ParentWindowWithContext(
-      view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
-      gfx::Rect());
-  view_->SetSize(view_size);
-  view_->Show();
-  sink_->ClearMessages();
-
-  // Accumulate some returned resources. This should trigger an IPC.
-  std::vector<viz::ReturnedResource> resources;
-  viz::ReturnedResource resource;
-  resource.id = 1;
-  resources.push_back(resource);
-  view_->renderer_compositor_frame_sink_->Reset();
-  view_->ReclaimResources(resources);
-  view_->renderer_compositor_frame_sink_->Flush();
-  EXPECT_FALSE(view_->renderer_compositor_frame_sink_->did_receive_ack());
-  EXPECT_FALSE(
-      view_->renderer_compositor_frame_sink_->last_reclaimed_resources()
-          .empty());
-}
-
-// This test verifies that when the CompositorFrameSink changes, the old
-// resources are not returned.
-TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
-  // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
-  // https://crbug.com/844469
-  if (features::IsVizDisplayCompositorEnabled())
-    return;
-
-  viz::SurfaceManager* manager = GetFrameSinkManager()->surface_manager();
-
-  gfx::Size view_size(100, 100);
-  gfx::Rect view_rect(view_size);
-
-  view_->InitAsChild(nullptr);
-  aura::client::ParentWindowWithContext(
-      view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
-      gfx::Rect());
-  view_->SetSize(view_size);
-  view_->Show();
-  sink_->ClearMessages();
-
-  // Submit a frame with resources.
-  viz::CompositorFrame frame = MakeDelegatedFrame(1.f, view_size, view_rect);
-  viz::TransferableResource resource;
-  resource.id = 1;
-  frame.resource_list.push_back(resource);
-  view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId, std::move(frame),
-                               base::nullopt);
-  EXPECT_EQ(0u, sink_->message_count());
-
-  // Signal that a new RendererCompositorFrameSink was created by the renderer.
-  view_->CreateNewRendererCompositorFrameSink();
-
-  // Submit another frame. The resources for the previous frame belong to the
-  // old RendererCompositorFrameSink and should not be returned.
-  view_->SubmitCompositorFrame(view_->surface_id().local_surface_id(),
-                               MakeDelegatedFrame(1.f, view_size, view_rect),
-                               base::nullopt);
-  EXPECT_EQ(0u, sink_->message_count());
-
-  // Report that the surface is drawn to trigger an ACK.
-  view_->renderer_compositor_frame_sink_->Reset();
-  viz::Surface* surface = manager->GetSurfaceForId(view_->surface_id());
-  EXPECT_TRUE(surface);
-  surface->SendAckToClient();
-  view_->renderer_compositor_frame_sink_->Flush();
-  EXPECT_TRUE(view_->renderer_compositor_frame_sink_->did_receive_ack());
-}
-
 // Resizing in fullscreen mode should send the up-to-date screen info.
 // http://crbug.com/324350
 TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
@@ -3242,24 +3136,9 @@
   EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), *view_->GetBackgroundColor());
 }
 
-// Resizing is disabled due to flakiness. Commit might come before
-// DrawWaiterForTest looks for compositor frame. crbug.com/759653
-TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
-  gfx::Size size1(100, 100);
-  gfx::Size size2(200, 200);
-  gfx::Size size3(300, 300);
-  parent_local_surface_id_allocator_.GenerateId();
-  viz::LocalSurfaceId id1 =
-      parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
-          .local_surface_id();
-  parent_local_surface_id_allocator_.GenerateId();
-  viz::LocalSurfaceId id2 =
-      parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
-          .local_surface_id();
-  parent_local_surface_id_allocator_.GenerateId();
-  viz::LocalSurfaceId id3 =
-      parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
-          .local_surface_id();
+TEST_F(RenderWidgetHostViewAuraTest, Resize) {
+  constexpr gfx::Size size1(100, 100);
+  constexpr gfx::Size size2(200, 200);
 
   aura::Window* root_window = parent_view_->GetNativeView()->GetRootWindow();
   view_->InitAsChild(nullptr);
@@ -3267,23 +3146,21 @@
       view_->GetNativeView(), root_window, gfx::Rect(size1));
   view_->Show();
   view_->SetSize(size1);
-  view_->SubmitCompositorFrame(
-      id1, MakeDelegatedFrame(1.f, size1, gfx::Rect(size1)), base::nullopt);
-  ui::DrawWaiterForTest::WaitForCommit(
-      root_window->GetHost()->compositor());
+  EXPECT_EQ(size1.ToString(), view_->GetRequestedRendererSize().ToString());
+  EXPECT_TRUE(widget_host_->visual_properties_ack_pending_for_testing());
+
   {
     cc::RenderFrameMetadata metadata;
     metadata.viewport_size_in_pixels = size1;
-    metadata.local_surface_id_allocation = base::nullopt;
     widget_host_->DidUpdateVisualProperties(metadata);
+    EXPECT_FALSE(widget_host_->visual_properties_ack_pending_for_testing());
   }
   sink_->ClearMessages();
-  // Resize logic is idle (no pending resize, no pending commit).
-  EXPECT_EQ(size1.ToString(), view_->GetRequestedRendererSize().ToString());
 
-  // Resize renderer, should produce a Resize message
+  // Resize the renderer. This should produce an UpdateVisualProperties IPC.
   view_->SetSize(size2);
   EXPECT_EQ(size2.ToString(), view_->GetRequestedRendererSize().ToString());
+  EXPECT_TRUE(widget_host_->visual_properties_ack_pending_for_testing());
   ASSERT_EQ(1u, sink_->message_count());
   {
     const IPC::Message* msg = sink_->GetMessageAt(0);
@@ -3293,77 +3170,19 @@
     WidgetMsg_UpdateVisualProperties::Read(msg, &params);
     EXPECT_EQ(size2, std::get<0>(params).new_size);
   }
-  // Send resize ack to observe new Resize messages.
+  // Render should send back RenderFrameMetadata with new size.
   {
     cc::RenderFrameMetadata metadata;
     metadata.viewport_size_in_pixels = size2;
-    metadata.local_surface_id_allocation = base::nullopt;
     widget_host_->DidUpdateVisualProperties(metadata);
+    EXPECT_FALSE(widget_host_->visual_properties_ack_pending_for_testing());
   }
   sink_->ClearMessages();
 
-  // Resize renderer again, before receiving a frame. Should not produce a
-  // Resize message.
-  view_->SetSize(size3);
-  EXPECT_EQ(size2.ToString(), view_->GetRequestedRendererSize().ToString());
-  EXPECT_EQ(0u, sink_->message_count());
-
-  // Receive a frame of the new size, should be skipped and not produce a Resize
-  // message.
-  view_->renderer_compositor_frame_sink_->Reset();
-  view_->SubmitCompositorFrame(
-      id3, MakeDelegatedFrame(1.f, size3, gfx::Rect(size3)), base::nullopt);
-  view_->renderer_compositor_frame_sink_->Flush();
-  // Expect the frame ack;
-  EXPECT_TRUE(view_->renderer_compositor_frame_sink_->did_receive_ack());
-  EXPECT_EQ(size2.ToString(), view_->GetRequestedRendererSize().ToString());
-
-  // Receive a frame of the correct size, should not be skipped and, and should
-  // produce a Resize message after the commit.
-  view_->renderer_compositor_frame_sink_->Reset();
-  view_->SubmitCompositorFrame(
-      id2, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), base::nullopt);
-  view_->renderer_compositor_frame_sink_->Flush();
-  viz::SurfaceId surface_id = view_->surface_id();
-  if (!surface_id.is_valid()) {
-    // No frame ack yet.
-    EXPECT_FALSE(view_->renderer_compositor_frame_sink_->did_receive_ack());
-  } else {
-    // Frame isn't desired size, so early ack.
-    EXPECT_TRUE(view_->renderer_compositor_frame_sink_->did_receive_ack());
-  }
-  EXPECT_EQ(size2.ToString(), view_->GetRequestedRendererSize().ToString());
-
-  // Wait for commit, then we should unlock the compositor and send a Resize
-  // message (and a frame ack)
-  ui::DrawWaiterForTest::WaitForCommit(
-      root_window->GetHost()->compositor());
-
-  bool has_resize = false;
-  for (uint32_t i = 0; i < sink_->message_count(); ++i) {
-    const IPC::Message* msg = sink_->GetMessageAt(i);
-    switch (msg->type()) {
-      case WidgetMsg_UpdateVisualProperties::ID: {
-        EXPECT_FALSE(has_resize);
-        WidgetMsg_UpdateVisualProperties::Param params;
-        WidgetMsg_UpdateVisualProperties::Read(msg, &params);
-        EXPECT_EQ(size3, std::get<0>(params).new_size);
-        has_resize = true;
-        break;
-      }
-      default:
-        ADD_FAILURE() << "Unexpected message " << msg->type();
-        break;
-    }
-  }
-  EXPECT_TRUE(has_resize);
-  {
-    cc::RenderFrameMetadata metadata;
-    metadata.viewport_size_in_pixels = size3;
-    metadata.local_surface_id_allocation = base::nullopt;
-    widget_host_->DidUpdateVisualProperties(metadata);
-  }
-  sink_->ClearMessages();
+  // Calling SetSize() with the current size should be a no-op.
+  view_->SetSize(size2);
+  EXPECT_FALSE(widget_host_->visual_properties_ack_pending_for_testing());
+  ASSERT_EQ(0u, sink_->message_count());
 }
 
 // This test verifies that the primary SurfaceId is populated on resize.
@@ -3403,41 +3222,6 @@
   EXPECT_EQ(gfx::Size(300, 300), view_->window_->layer()->bounds().size());
 }
 
-// This test verifies that changing the CompositorFrameSink (and thus evicting
-// the current surface) does not crash,
-TEST_F(RenderWidgetHostViewAuraTest, CompositorFrameSinkChange) {
-  // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
-  // https://crbug.com/844469
-  if (features::IsVizDisplayCompositorEnabled())
-    return;
-
-  gfx::Rect view_rect(100, 100);
-  gfx::Size frame_size = view_rect.size();
-
-  view_->InitAsChild(nullptr);
-  aura::client::ParentWindowWithContext(
-      view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
-      gfx::Rect());
-  view_->SetSize(view_rect.size());
-
-  // Swap a frame.
-  view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
-                               MakeDelegatedFrame(1.f, frame_size, view_rect),
-                               base::nullopt);
-  view_->RunOnCompositingDidCommit();
-
-  // Signal that a new RendererCompositorFrameSink was created.
-  view_->CreateNewRendererCompositorFrameSink();
-
-  // Submit a frame from the new RendererCompositorFrameSink.
-  parent_local_surface_id_allocator_.GenerateId();
-  view_->SubmitCompositorFrame(
-      parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
-          .local_surface_id(),
-      MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
-  view_->RunOnCompositingDidCommit();
-}
-
 // This test verifies that frame eviction plays well with surface
 // synchronization.
 TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
@@ -3642,55 +3426,6 @@
   view_->OnTouchEvent(&release);
 }
 
-// Tests that BeginFrameAcks are forwarded correctly from the
-// SwapCompositorFrame and OnDidNotProduceFrame IPCs through DelegatedFrameHost
-// and its CompositorFrameSinkSupport.
-TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
-  // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
-  // https://crbug.com/844469
-  if (features::IsVizDisplayCompositorEnabled())
-    return;
-
-  gfx::Rect view_rect(100, 100);
-  gfx::Size frame_size = view_rect.size();
-  viz::LocalSurfaceId local_surface_id = kArbitraryLocalSurfaceId;
-
-  view_->InitAsChild(nullptr);
-  aura::client::ParentWindowWithContext(
-      view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
-      gfx::Rect());
-  view_->SetSize(view_rect.size());
-
-  viz::FakeSurfaceObserver observer;
-  viz::SurfaceManager* surface_manager =
-      GetFrameSinkManager()->surface_manager();
-  surface_manager->AddObserver(&observer);
-
-  view_->SetNeedsBeginFrames(true);
-  constexpr uint64_t source_id = 10;
-
-  {
-    // Ack from CompositorFrame is forwarded.
-    viz::BeginFrameAck ack(source_id, 5, true);
-    viz::CompositorFrame frame = MakeDelegatedFrame(1.f, frame_size, view_rect);
-    frame.metadata.begin_frame_ack = ack;
-    view_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                 base::nullopt);
-    view_->RunOnCompositingDidCommit();
-    EXPECT_EQ(ack, observer.last_ack());
-  }
-
-  {
-    // Explicit ack through OnDidNotProduceFrame is forwarded.
-    viz::BeginFrameAck ack(source_id, 6, false);
-    view_->OnDidNotProduceFrame(ack);
-    EXPECT_EQ(ack, observer.last_ack());
-  }
-
-  surface_manager->RemoveObserver(&observer);
-  view_->SetNeedsBeginFrames(false);
-}
-
 TEST_F(RenderWidgetHostViewAuraTest, VisibleViewportTest) {
   gfx::Rect view_rect(100, 100);
 
@@ -5670,44 +5405,6 @@
             gesture_event->primary_pointer_type);
 }
 
-// Verify that a hit test region list that was provided to the view in a
-// SubmitCompositorFrame becomes the active hit test region in the
-// viz::HitTestManager.
-TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
-  // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
-  // https://crbug.com/844469
-  if (features::IsVizDisplayCompositorEnabled())
-    return;
-
-  gfx::Rect view_rect(0, 0, 100, 100);
-  gfx::Size frame_size = view_rect.size();
-
-  view_->InitAsChild(nullptr);
-  aura::client::ParentWindowWithContext(
-      view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
-      gfx::Rect());
-  view_->SetSize(view_rect.size());
-
-  viz::SurfaceId surface_id(view_->GetFrameSinkId(), kArbitraryLocalSurfaceId);
-
-  base::Optional<viz::HitTestRegionList> hit_test_region_list(base::in_place);
-  hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine;
-  hit_test_region_list->bounds.SetRect(0, 0, 100, 100);
-  view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
-                               MakeDelegatedFrame(1.f, frame_size, view_rect),
-                               std::move(hit_test_region_list));
-
-  viz::TestLatestLocalSurfaceIdLookupDelegate delegate;
-  delegate.SetSurfaceIdMap(
-      viz::SurfaceId(view_->GetFrameSinkId(), kArbitraryLocalSurfaceId));
-  const viz::HitTestRegionList* active_hit_test_region_list =
-      GetFrameSinkManager()->hit_test_manager()->GetActiveHitTestRegionList(
-          &delegate, surface_id.frame_sink_id());
-  EXPECT_EQ(active_hit_test_region_list->flags,
-            viz::HitTestRegionFlags::kHitTestMine);
-  EXPECT_EQ(active_hit_test_region_list->bounds, view_rect);
-}
-
 // Test that the rendering timeout for newly loaded content fires when enough
 // time passes without receiving a new compositor frame.
 TEST_F(RenderWidgetHostViewAuraTest, NewContentRenderingTimeout) {
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index bcd9bb9..2dcc608 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -273,14 +273,6 @@
   virtual void FocusedNodeChanged(bool is_editable_node,
                                   const gfx::Rect& node_bounds_in_screen) {}
 
-  // This method is called by RenderWidgetHostImpl when a new
-  // RendererCompositorFrameSink is created in the renderer. The view is
-  // expected not to return resources belonging to the old
-  // RendererCompositorFrameSink after this method finishes.
-  virtual void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient*
-          renderer_compositor_frame_sink) = 0;
-
   // This is called by the RenderWidgetHostImpl to provide a new compositor
   // frame that was received from the renderer process. if Viz service hit
   // testing is enabled then a HitTestRegionList provides hit test data
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 829ce3a..8c9cd641 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -14,14 +14,10 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/host/host_frame_sink_manager.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
-#include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_manager.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/compositor/surface_utils.h"
@@ -64,13 +60,11 @@
       frame_sink_id_(
           base::checked_cast<uint32_t>(widget_host->GetProcess()->GetID()),
           base::checked_cast<uint32_t>(widget_host->GetRoutingID())),
-      frame_connector_(nullptr),
-      enable_viz_(features::IsVizDisplayCompositorEnabled()) {
+      frame_connector_(nullptr) {
   GetHostFrameSinkManager()->RegisterFrameSinkId(
       frame_sink_id_, this, viz::ReportFirstSurfaceActivation::kNo);
   GetHostFrameSinkManager()->SetFrameSinkDebugLabel(
       frame_sink_id_, "RenderWidgetHostViewChildFrame");
-  CreateCompositorFrameSinkSupport();
 }
 
 RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
@@ -80,7 +74,6 @@
   if (frame_connector_)
     DetachFromTouchSelectionClientManagerIfNecessary();
 
-  ResetCompositorFrameSinkSupport();
   if (GetHostFrameSinkManager())
     GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
 }
@@ -538,19 +531,6 @@
   NOTREACHED();
 }
 
-void RenderWidgetHostViewChildFrame::DidReceiveCompositorFrameAck(
-    const std::vector<viz::ReturnedResource>& resources) {
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-}
-
-void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  ResetCompositorFrameSinkSupport();
-  renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
-  CreateCompositorFrameSinkSupport();
-}
-
 void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
     const viz::FrameSinkId& parent_frame_sink_id) {
   if (parent_frame_sink_id_ == parent_frame_sink_id)
@@ -583,17 +563,12 @@
     const viz::LocalSurfaceId& local_surface_id,
     viz::CompositorFrame frame,
     base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  DCHECK(!enable_viz_);
-  TRACE_EVENT0("content",
-               "RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
-  support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                  std::move(hit_test_region_list));
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewChildFrame::OnDidNotProduceFrame(
     const viz::BeginFrameAck& ack) {
-  DCHECK(!enable_viz_);
-  support_->DidNotProduceFrame(ack);
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewChildFrame::TransformPointToRootSurface(
@@ -836,25 +811,6 @@
                                                  std::move(request));
 }
 
-void RenderWidgetHostViewChildFrame::ReclaimResources(
-    const std::vector<viz::ReturnedResource>& resources) {
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->ReclaimResources(resources);
-}
-
-void RenderWidgetHostViewChildFrame::OnBeginFrame(
-    const viz::BeginFrameArgs& args,
-    const viz::FrameTimingDetailsMap& timing_details) {
-  host_->ProgressFlingIfNeeded(args.frame_time);
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->OnBeginFrame(args, timing_details);
-}
-
-void RenderWidgetHostViewChildFrame::OnBeginFramePausedChanged(bool paused) {
-  if (renderer_compositor_frame_sink_)
-    renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
-}
-
 void RenderWidgetHostViewChildFrame::OnFirstSurfaceActivation(
     const viz::SurfaceInfo& surface_info) {}
 
@@ -862,12 +818,6 @@
   OnFrameTokenChangedForView(frame_token);
 }
 
-void RenderWidgetHostViewChildFrame::SetNeedsBeginFrames(
-    bool needs_begin_frames) {
-  if (support_)
-    support_->SetNeedsBeginFrame(needs_begin_frames);
-}
-
 TouchSelectionControllerClientManager*
 RenderWidgetHostViewChildFrame::GetTouchSelectionControllerClientManager() {
   if (!frame_connector_)
@@ -891,11 +841,6 @@
   }
 }
 
-void RenderWidgetHostViewChildFrame::SetWantsAnimateOnlyBeginFrames() {
-  if (support_)
-    support_->SetWantsAnimateOnlyBeginFrames();
-}
-
 void RenderWidgetHostViewChildFrame::TakeFallbackContentFrom(
     RenderWidgetHostView* view) {
   // This method only makes sense for top-level views.
@@ -996,32 +941,6 @@
   return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
 }
 
-void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
-  if (enable_viz_)
-    return;
-
-  DCHECK(!support_);
-  constexpr bool is_root = false;
-  support_ = GetHostFrameSinkManager()->CreateCompositorFrameSinkSupport(
-      this, frame_sink_id_, is_root);
-  if (parent_frame_sink_id_.is_valid()) {
-    GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
-                                                          frame_sink_id_);
-  }
-  if (host()->needs_begin_frames())
-    support_->SetNeedsBeginFrame(true);
-}
-
-void RenderWidgetHostViewChildFrame::ResetCompositorFrameSinkSupport() {
-  if (!support_)
-    return;
-  if (parent_frame_sink_id_.is_valid()) {
-    GetHostFrameSinkManager()->UnregisterFrameSinkHierarchy(
-        parent_frame_sink_id_, frame_sink_id_);
-  }
-  support_.reset();
-}
-
 ui::TextInputType RenderWidgetHostViewChildFrame::GetTextInputType() const {
   if (!text_input_manager_)
     return ui::TEXT_INPUT_TYPE_NONE;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 325f94c..b1aed43 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -33,10 +33,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 
-namespace viz {
-class CompositorFrameSinkSupport;
-}
-
 namespace content {
 class FrameConnectorDelegate;
 class RenderWidgetHost;
@@ -54,7 +50,6 @@
 class CONTENT_EXPORT RenderWidgetHostViewChildFrame
     : public RenderWidgetHostViewBase,
       public TouchSelectionControllerClientManager::Observer,
-      public viz::mojom::CompositorFrameSinkClient,
       public viz::HostFrameSinkClient {
  public:
   static RenderWidgetHostViewChildFrame* Create(RenderWidgetHost* widget);
@@ -100,8 +95,8 @@
   gfx::NativeView GetNativeView() override;
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
   bool IsMouseLocked() override;
-  void SetNeedsBeginFrames(bool needs_begin_frames) override;
-  void SetWantsAnimateOnlyBeginFrames() override;
+  void SetNeedsBeginFrames(bool needs_begin_frames) override {}
+  void SetWantsAnimateOnlyBeginFrames() override {}
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
 
   // RenderWidgetHostViewBase implementation.
@@ -118,9 +113,6 @@
   void SetTooltipText(const base::string16& tooltip_text) override;
   void GestureEventAck(const blink::WebGestureEvent& event,
                        InputEventAckState ack_result) override;
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
-      override;
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
@@ -184,15 +176,6 @@
   viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
       const cc::RenderFrameMetadata& metadata) override;
 
-  // viz::mojom::CompositorFrameSinkClient implementation.
-  void DidReceiveCompositorFrameAck(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFrame(const viz::BeginFrameArgs& args,
-                    const viz::FrameTimingDetailsMap& timing_details) override;
-  void ReclaimResources(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFramePausedChanged(bool paused) override;
-
   // viz::HostFrameSinkClient implementation.
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
@@ -250,7 +233,6 @@
   viz::FrameSinkId frame_sink_id_;
 
   // Surface-related state.
-  std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
   viz::SurfaceInfo last_activated_surface_info_;
   gfx::Rect last_screen_rect_;
 
@@ -273,8 +255,6 @@
 
   virtual void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info);
 
-  void CreateCompositorFrameSinkSupport();
-  void ResetCompositorFrameSinkSupport();
   void DetachFromTouchSelectionClientManagerIfNecessary();
 
   // Returns false if the view cannot be shown. This is the case where the frame
@@ -296,10 +276,6 @@
   // The surface client ID of the parent RenderWidgetHostView.  0 if none.
   viz::FrameSinkId parent_frame_sink_id_;
 
-  const bool enable_viz_;
-  viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
-      nullptr;
-
   gfx::RectF last_stable_screen_rect_;
   base::TimeTicks screen_rect_stable_since_;
 
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 10ac49f..7875e19 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
@@ -139,16 +139,6 @@
         new MockFrameConnectorDelegate(use_zoom_for_device_scale_factor);
     test_frame_connector_->SetView(view_);
     view_->SetFrameConnectorDelegate(test_frame_connector_);
-
-    mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink;
-    mojo::PendingReceiver<viz::mojom::CompositorFrameSink> sink_receiver =
-        sink.InitWithNewPipeAndPassReceiver();
-    renderer_compositor_frame_sink_ =
-        std::make_unique<FakeRendererCompositorFrameSink>(
-            std::move(sink), renderer_compositor_frame_sink_remote_
-                                 .BindNewPipeAndPassReceiver());
-    view_->DidCreateNewRendererCompositorFrameSink(
-        renderer_compositor_frame_sink_remote_.get());
   }
 
   void TearDown() override {
@@ -189,14 +179,6 @@
   RenderWidgetHostImpl* widget_host_;
   RenderWidgetHostViewChildFrame* view_;
   MockFrameConnectorDelegate* test_frame_connector_;
-  std::unique_ptr<FakeRendererCompositorFrameSink>
-      renderer_compositor_frame_sink_;
-
- private:
-  mojo::Remote<viz::mojom::CompositorFrameSinkClient>
-      renderer_compositor_frame_sink_remote_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrameTest);
 };
 
 viz::CompositorFrame CreateDelegatedFrame(float scale_factor,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index fb8589f..3d5f4a73 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -114,9 +114,9 @@
   void SetActive(bool active) override;
   void ShowDefinitionForSelection() override;
   void SpeakSelection() override;
-  void SetNeedsBeginFrames(bool needs_begin_frames) override;
   void GetScreenInfo(ScreenInfo* screen_info) override;
-  void SetWantsAnimateOnlyBeginFrames() override;
+  void SetNeedsBeginFrames(bool needs_begin_frames) override {}
+  void SetWantsAnimateOnlyBeginFrames() override {}
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
 
   // Implementation of RenderWidgetHostViewBase.
@@ -143,9 +143,6 @@
   void EnsureSurfaceSynchronizedForWebTest() override;
   void FocusedNodeChanged(bool is_editable_node,
                           const gfx::Rect& node_bounds_in_screen) override;
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
-      override;
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
@@ -400,7 +397,6 @@
 
   // BrowserCompositorMacClient implementation.
   SkColor BrowserCompositorMacGetGutterColor() const override;
-  void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
   void DestroyCompositorForShutdown() override;
   bool OnBrowserCompositorSurfaceIdChanged() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 7fd751b7..f1b2251d 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -84,13 +84,6 @@
   return last_frame_root_background_color_;
 }
 
-void RenderWidgetHostViewMac::BrowserCompositorMacOnBeginFrame(
-    base::TimeTicks frame_time) {
-  // ProgressFling must get called for middle click autoscroll fling on Mac.
-  if (host())
-    host()->ProgressFlingIfNeeded(frame_time);
-}
-
 void RenderWidgetHostViewMac::OnFrameTokenChanged(uint32_t frame_token) {
   OnFrameTokenChangedForView(frame_token);
 }
@@ -850,22 +843,15 @@
   browser_compositor_->ForceNewSurfaceId();
 }
 
-void RenderWidgetHostViewMac::SetNeedsBeginFrames(bool needs_begin_frames) {
-  NOTREACHED();
-}
-
 void RenderWidgetHostViewMac::OnDidUpdateVisualPropertiesComplete(
     const cc::RenderFrameMetadata& metadata) {
   browser_compositor_->UpdateSurfaceFromChild(
-      metadata.device_scale_factor, metadata.viewport_size_in_pixels,
+      host()->auto_resize_enabled(), metadata.device_scale_factor,
+      metadata.viewport_size_in_pixels,
       metadata.local_surface_id_allocation.value_or(
           viz::LocalSurfaceIdAllocation()));
 }
 
-void RenderWidgetHostViewMac::SetWantsAnimateOnlyBeginFrames() {
-  browser_compositor_->SetWantsAnimateOnlyBeginFrames();
-}
-
 void RenderWidgetHostViewMac::TakeFallbackContentFrom(
     RenderWidgetHostView* view) {
   DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)
@@ -1065,28 +1051,16 @@
   }
 }
 
-void RenderWidgetHostViewMac::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  browser_compositor_->DidCreateNewRendererCompositorFrameSink(
-      renderer_compositor_frame_sink);
-}
-
 void RenderWidgetHostViewMac::SubmitCompositorFrame(
     const viz::LocalSurfaceId& local_surface_id,
     viz::CompositorFrame frame,
     base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
-
-  page_at_minimum_scale_ =
-      frame.metadata.page_scale_factor == frame.metadata.min_page_scale_factor;
-
-  browser_compositor_->GetDelegatedFrameHost()->SubmitCompositorFrame(
-      local_surface_id, std::move(frame), std::move(hit_test_region_list));
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewMac::OnDidNotProduceFrame(
     const viz::BeginFrameAck& ack) {
-  browser_compositor_->OnDidNotProduceFrame(ack);
+  NOTREACHED();
 }
 
 void RenderWidgetHostViewMac::ResetFallbackToFirstNavigationSurface() {
@@ -1604,6 +1578,8 @@
   // If the page is at the minimum zoom level, require a threshold be reached
   // before the pinch has an effect. Synthetic pinches are not subject to this
   // threshold.
+  // TODO(crbug.com/1038683): |page_at_minimum_scale_| is always true, should it
+  // be removed or correctly set based on RenderFrameMetadata?
   if (page_at_minimum_scale_) {
     pinch_has_reached_zoom_threshold_ = is_synthetically_injected;
     pinch_unused_amount_ = 1;
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index dd2876a..5171535 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -106,7 +106,7 @@
     const ui::LatencyInfo& latency) {
   this->root_view = std::move(root_view);
   this->location = ComputeEventLocation(event);
-  this->event = event.Clone();
+  this->event = ui::WebInputEventTraits::Clone(event);
   this->latency = latency;
 }
 
diff --git a/content/browser/service_worker/README.md b/content/browser/service_worker/README.md
index c7ae0d5e..a1dacf3 100644
--- a/content/browser/service_worker/README.md
+++ b/content/browser/service_worker/README.md
@@ -26,6 +26,8 @@
 This document describes Chromium's implementation of [service
 workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
 
+[TOC]
+
 ## Introduction to service workers
 
 This section briefly introduces what service workers are. For a more detailed
@@ -217,6 +219,104 @@
 service worker controls the client and manages request interception to that
 service worker.
 
+### Mojo
+
+[Mojo](/mojo/README.md) is Chromium's IPC system and plays a important role in
+service worker architecture. This section describes the main Mojo interfaces for
+service workers, and which message pipes they are on.
+
+#### Browser <->  Renderer (window)
+
+For windows, the browser process and renderer process talk over Mojo interfaces
+bound to the legacy IPC "channel" message pipe.
+
+Each window in the renderer process is connected to a host in the browser
+process. The renderer talks to the browser process over the
+`mojom.blink.ServiceWorkerContainerHost` interface which provides functionality
+like registering service workers. The browser talks to the renderer over the
+`mojom.blink.ServiceWorkerContainer` interface.
+
+The window obtains `ServiceWorkerRegistration` and `ServiceWorker` JavaScript
+objects via APIs like `navigator.serviceWorker.ready` and
+`navigator.serviceWorker.controller`, and `navigator.serviceWorker.register()`.
+Each object has a connection to the browser, again on the channel-associated
+message pipe. `ServiceWorkerRegistration` has a remote to a
+`mojom.blink.ServiceWorkerRegistrationObjectHost` and `ServiceWorker` has a
+remote to a `ServiceWorkerObjectHost`. Conversely, the browser process has
+remotes to `mojom.blink.ServiceWorkerRegistrationObject` and
+`mojom.blink.ServiceWorkerRegistration`.
+
+> After making this design, there's been some realization that this "too
+> mojofied". It may have worked better to use fewer interfaces, e.g., a single
+> ServiceWorkerContainer interface from which one can manipulate
+> ServiceWorkerRegistration and ServiceWorker.
+
+#### Browser <-> Renderer (shared worker)
+
+For shared workers, the browser process and renderer process talk over Mojo
+interfaces bound to the dedicated message pipe established by
+the `mojom.blink.SharedWorkerFactory` implementation that creates the shared
+worker.
+
+Similar to windows, the shared worker has a remote to a
+`mojom.blink.ServiceWorkerContainerHost` in the browser process, and the
+browser process has a remote to the `mojom.blink.ServiceWorkerContainer`
+in the renderer process.
+
+However, shared workers don't yet support `navigator.serviceWorker`,
+so they don't use many of the methods on `ServiceWorkerContainerHost`.
+They also don't yet have a way to obtain a `ServiceWorkerRegistration`
+or `ServiceWorker` JavaScript object.
+
+#### Browser <-> Renderer (service worker)
+
+For service workers, there are two message pipes: a) a "bootstrap" message
+pipe for starting/stopping the service worker thread, and b) a message pipe
+bound to the running service worker thread.
+
+The "bootstrap" message pipe is established by the
+`mojom.blink.EmbeddedWorkerInstanceClient` implementation in the renderer.  The
+browser process uses this interface to ask the renderer process to start and
+stop a service worker thread. The renderer process has a remote to a
+corresponding `mojom.blink.EmbeddedWorkerInstanceHost` in the browser process.
+
+In addition, like windows and shared workers above, the service worker has a
+remote to a `mojom.blink.ServiceWorkerContainerHost` in the brocess process, and
+the browser process has a remote to a `mojom.blink.ServiceWorkerContainer`.
+These are on the bootstrap message pipe.
+
+> Note: It's unclear why service workers use the `ServiceWorkerContainerHost`
+> interface, because they are forbidden from calling any methods on this
+> interface.  There are some plans to clean this up, see
+> https://crbug.com/931087.
+
+Running service worker threads have a dedicated message pipe, established by the
+`mojom.blink.ServiceWorker` implementation. The browser process uses this
+interface to ask the renderer to dispatch events to the service worker. The
+service worker has a remote to a corresponding `mojom.blink.ServiceWorkerHost`
+in the browser process.
+
+Service workers have access to a `ServiceWorkerRegistration` JavaScript object
+via `self.registration` and its `ServiceWorker` properties. The
+`mojom.blink.ServiceWorker(Registration)Object(Host)` interfaces are bound to
+the service worker thread's message pipe.
+
+#### Renderer (window or shared worker) <-> Renderer (service worker)
+
+Service worker clients in a renderer process have a direct connection to their
+controller service worker, which can be in the same process or a different
+process. The clients have a remote to a `mojom.blink.ControllerServiceWorker`
+which they use to dispatch fetch events to the service worker.
+
+This remote is given to the client by the browser process using
+`SetController()` on the `mojom.blink.ServiceWorkerContainer` interface.  The
+browser is the source of truth about which service worker is controlling which
+client.
+
+If the connection breaks, it likely means the service worker has stopped. The
+service worker client asks the browser process to restart the service worker so
+it can again dispatch fetch events to it.
+
 ## Directory structure
 
 - [content/browser/service_worker]: Browser process code, including stored
diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
index eddda8e..8658a6c 100644
--- a/content/browser/service_worker/service_worker_client_utils.cc
+++ b/content/browser/service_worker/service_worker_client_utils.cc
@@ -436,7 +436,8 @@
   } else if (controller->context()) {
     GURL origin = controller->script_url().GetOrigin();
     for (auto it = controller->context()->GetClientContainerHostIterator(
-             origin, false /* include_reserved_clients */);
+             origin, false /* include_reserved_clients */,
+             false /* include_back_forward_cached_clients */);
          !it->IsAtEnd(); it->Advance()) {
       AddNonWindowClient(it->GetContainerHost(), options->client_type,
                          &clients);
@@ -476,7 +477,8 @@
   } else if (controller->context()) {
     GURL origin = controller->script_url().GetOrigin();
     for (auto it = controller->context()->GetClientContainerHostIterator(
-             origin, false /* include_reserved_clients */);
+             origin, false /* include_reserved_clients */,
+             false /* include_back_forward_cached_clients */);
          !it->IsAtEnd(); it->Advance()) {
       AddWindowClient(it->GetContainerHost(), &clients_info);
     }
@@ -682,7 +684,8 @@
 
   for (std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator> it =
            context->GetClientContainerHostIterator(
-               origin, true /* include_reserved_clients */);
+               origin, true /* include_reserved_clients */,
+               false /* include_back_forward_cached_clients */);
        !it->IsAtEnd(); it->Advance()) {
     ServiceWorkerContainerHost* container_host = it->GetContainerHost();
     DCHECK(container_host->IsContainerForClient());
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 3ae2ed3..2288870 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -125,15 +125,18 @@
 bool IsSameOriginClientContainerHost(
     const GURL& origin,
     bool allow_reserved_client,
+    bool allow_back_forward_cached_client,
     ServiceWorkerContainerHost* container_host) {
   DCHECK(container_host->IsContainerForClient());
   // If |container_host| is in BackForwardCache, it should be skipped in
   // iteration, because (1) hosts in BackForwardCache should never be exposed to
   // web as clients and (2) hosts could be in an unknown state after eviction
   // and before deletion.
-  if (IsBackForwardCacheEnabled()) {
-    if (container_host->IsInBackForwardCache())
-      return false;
+  // When |allow_back_forward_cached_client| is true, do not skip the cached
+  // client.
+  if (!allow_back_forward_cached_client &&
+      container_host->IsInBackForwardCache()) {
+    return false;
   }
   return container_host->url().GetOrigin() == origin &&
          (allow_reserved_client || container_host->is_execution_ready());
@@ -339,12 +342,14 @@
 std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator>
 ServiceWorkerContextCore::GetClientContainerHostIterator(
     const GURL& origin,
-    bool include_reserved_clients) {
+    bool include_reserved_clients,
+    bool include_back_forward_cached_clients) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   return base::WrapUnique(new ContainerHostIterator(
       container_host_by_uuid_.get(),
       base::BindRepeating(IsSameOriginClientContainerHost, origin,
-                          include_reserved_clients)));
+                          include_reserved_clients,
+                          include_back_forward_cached_clients)));
 }
 
 std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator>
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index f470715..c278c4b3 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -164,13 +164,15 @@
   void RemoveProviderHost(int provider_id);
 
   // Returns a ContainerHost iterator for all service worker clients for the
-  // |origin|. If |include_reserved_clients| is false, this only returns clients
-  // that are execution ready (i.e., for windows, the document has been
-  // created and for workers, the final response after redirects has been
-  // delivered).
+  // |origin|. If |include_reserved_clients| is true, this includes clients that
+  // are not execution ready (i.e., for windows, the document has not yet been
+  // created and for workers, the final response after redirects has not yet
+  // been delivered). If |include_back_forward_cached_clients| is true, this
+  // includes the clients whose documents are stored in BackForward Cache.
   std::unique_ptr<ContainerHostIterator> GetClientContainerHostIterator(
       const GURL& origin,
-      bool include_reserved_clients);
+      bool include_reserved_clients,
+      bool include_back_forward_cached_clients);
 
   // Returns a ContainerHost iterator for service worker window clients for the
   // |origin|. If |include_reserved_clients| is false, this only returns clients
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index 628ba9d..8a6e7009 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -1031,7 +1031,8 @@
   // Iterate over the client container hosts that belong to kOrigin1.
   std::set<ServiceWorkerContainerHost*> results;
   for (auto it = context()->GetClientContainerHostIterator(
-           kOrigin1, true /* include_reserved_clients */);
+           kOrigin1, true /* include_reserved_clients */,
+           false /* include_back_forward_cached_clients */);
        !it->IsAtEnd(); it->Advance()) {
     results.insert(it->GetContainerHost());
   }
@@ -1043,7 +1044,8 @@
   // (This should not include host4 as it's not for controllee.)
   results.clear();
   for (auto it = context()->GetClientContainerHostIterator(
-           kOrigin2, true /* include_reserved_clients */);
+           kOrigin2, true /* include_reserved_clients */,
+           false /* include_back_forward_cached_clients */);
        !it->IsAtEnd(); it->Advance()) {
     results.insert(it->GetContainerHost());
   }
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index c58e99faf..e07510a 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -337,7 +337,7 @@
   friend class FakeServiceWorkerContextWrapper;
   friend class ServiceWorkerClientsApiBrowserTest;
   friend class ServiceWorkerInternalsUI;
-  friend class ServiceWorkerNavigationHandleCore;
+  friend class ServiceWorkerMainResourceHandleCore;
   friend class ServiceWorkerProcessManager;
   friend class ServiceWorkerRequestHandler;
   friend class ServiceWorkerVersionBrowserTest;
diff --git a/content/browser/service_worker/service_worker_navigation_handle.cc b/content/browser/service_worker/service_worker_main_resource_handle.cc
similarity index 69%
rename from content/browser/service_worker/service_worker_navigation_handle.cc
rename to content/browser/service_worker/service_worker_main_resource_handle.cc
index 788e1eb..2f237251 100644
--- a/content/browser/service_worker/service_worker_navigation_handle.cc
+++ b/content/browser/service_worker/service_worker_main_resource_handle.cc
@@ -2,36 +2,36 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 
 #include <utility>
 
 #include "base/bind.h"
 #include "base/task/post_task.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace content {
 
-ServiceWorkerNavigationHandle::ServiceWorkerNavigationHandle(
+ServiceWorkerMainResourceHandle::ServiceWorkerMainResourceHandle(
     ServiceWorkerContextWrapper* context_wrapper)
     : context_wrapper_(context_wrapper) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  core_ = new ServiceWorkerNavigationHandleCore(weak_factory_.GetWeakPtr(),
-                                                context_wrapper);
+  core_ = new ServiceWorkerMainResourceHandleCore(weak_factory_.GetWeakPtr(),
+                                                  context_wrapper);
 }
 
-ServiceWorkerNavigationHandle::~ServiceWorkerNavigationHandle() {
+ServiceWorkerMainResourceHandle::~ServiceWorkerMainResourceHandle() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  // Delete the ServiceWorkerNavigationHandleCore on the core thread.
+  // Delete the ServiceWorkerMainResourceHandleCore on the core thread.
   BrowserThread::DeleteSoon(ServiceWorkerContext::GetCoreThreadId(), FROM_HERE,
                             core_);
 }
 
-void ServiceWorkerNavigationHandle::OnCreatedProviderHost(
+void ServiceWorkerMainResourceHandle::OnCreatedProviderHost(
     blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(provider_info->host_remote.is_valid() &&
@@ -40,7 +40,7 @@
   provider_info_ = std::move(provider_info);
 }
 
-void ServiceWorkerNavigationHandle::OnBeginNavigationCommit(
+void ServiceWorkerMainResourceHandle::OnBeginNavigationCommit(
     int render_process_id,
     int render_frame_id,
     network::mojom::CrossOriginEmbedderPolicy cross_origin_embedder_policy,
@@ -52,18 +52,18 @@
   ServiceWorkerContextWrapper::RunOrPostTaskOnCoreThread(
       FROM_HERE,
       base::BindOnce(
-          &ServiceWorkerNavigationHandleCore::OnBeginNavigationCommit,
+          &ServiceWorkerMainResourceHandleCore::OnBeginNavigationCommit,
           base::Unretained(core_), render_process_id, render_frame_id,
           cross_origin_embedder_policy));
   *out_provider_info = std::move(provider_info_);
 }
 
-void ServiceWorkerNavigationHandle::OnBeginWorkerCommit(
+void ServiceWorkerMainResourceHandle::OnBeginWorkerCommit(
     network::mojom::CrossOriginEmbedderPolicy cross_origin_embedder_policy) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ServiceWorkerContextWrapper::RunOrPostTaskOnCoreThread(
       FROM_HERE,
-      base::BindOnce(&ServiceWorkerNavigationHandleCore::OnBeginWorkerCommit,
+      base::BindOnce(&ServiceWorkerMainResourceHandleCore::OnBeginWorkerCommit,
                      base::Unretained(core_), cross_origin_embedder_policy));
 }
 
diff --git a/content/browser/service_worker/service_worker_navigation_handle.h b/content/browser/service_worker/service_worker_main_resource_handle.h
similarity index 65%
rename from content/browser/service_worker/service_worker_navigation_handle.h
rename to content/browser/service_worker/service_worker_main_resource_handle.h
index ff9d6a5..13fc021 100644
--- a/content/browser/service_worker/service_worker_navigation_handle.h
+++ b/content/browser/service_worker/service_worker_main_resource_handle.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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_H_
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -14,47 +14,45 @@
 namespace content {
 
 class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandleCore;
+class ServiceWorkerMainResourceHandleCore;
 
 // This class is used to manage the lifetime of ServiceWorkerProviderHosts
 // created for main resource requests (navigations and web workers). This is a
 // UI thread class, with a pendant class on the core thread, the
-// ServiceWorkerNavigationHandleCore.
+// ServiceWorkerMainResourceHandleCore.
 //
-// The lifetime of the ServiceWorkerNavigationHandle, the
-// ServiceWorkerNavigationHandleCore and the ServiceWorkerProviderHost are the
+// The lifetime of the ServiceWorkerMainResourceHandle, the
+// ServiceWorkerMainResourceHandleCore and the ServiceWorkerProviderHost are the
 // following:
-//   1) We create a ServiceWorkerNavigationHandle on the UI thread without
+//   1) We create a ServiceWorkerMainResourceHandle on the UI thread without
 //   populating the member service worker provider info. This also leads to the
-//   creation of a ServiceWorkerNavigationHandleCore.
+//   creation of a ServiceWorkerMainResourceHandleCore.
 //
 //   2) When the navigation request is sent to the core thread, we include a
-//   pointer to the ServiceWorkerNavigationHandleCore.
+//   pointer to the ServiceWorkerMainResourceHandleCore.
 //
 //   3) If we pre-create a ServiceWorkerProviderHost for this navigation, it
 //   is added to ServiceWorkerContextCore and its provider info is passed to
-//   ServiceWorkerNavigationHandle on the UI thread via
-//   ServiceWorkerNavigationHandleCore. See
-//   ServiceWorkerNavigationHandleCore::OnCreatedProviderHost() and
-//   ServiceWorkerNavigationHandle::OnCreatedProviderHost() for details.
+//   ServiceWorkerMainResourceHandle on the UI thread via
+//   ServiceWorkerMainResourceHandleCore. See
+//   ServiceWorkerMainResourceHandleCore::OnCreatedProviderHost() and
+//   ServiceWorkerMainResourceHandle::OnCreatedProviderHost() for details.
 //
 //   4) When the navigation is ready to commit, the NavigationRequest will
-//   call ServiceWorkerNavigationHandle::OnBeginNavigationCommit() to
+//   call ServiceWorkerMainResourceHandle::OnBeginNavigationCommit() to
 //     - complete the initialization for the ServiceWorkerProviderHost.
 //     - take out the provider info to be sent as part of navigation commit IPC.
 //
-//   5) When the navigation finishes, the ServiceWorkerNavigationHandle is
-//   destroyed. The destructor of the ServiceWorkerNavigationHandle destroys
+//   5) When the navigation finishes, the ServiceWorkerMainResourceHandle is
+//   destroyed. The destructor of the ServiceWorkerMainResourceHandle destroys
 //   the provider info which in turn leads to the destruction of an unclaimed
 //   ServiceWorkerProviderHost, and posts a task to destroy the
-//   ServiceWorkerNavigationHandleCore on the core thread.
-//
-// TODO(falken): Rename ServiceWorkerMainResourceHandle.
-class CONTENT_EXPORT ServiceWorkerNavigationHandle {
+//   ServiceWorkerMainResourceHandleCore on the core thread.
+class CONTENT_EXPORT ServiceWorkerMainResourceHandle {
  public:
-  explicit ServiceWorkerNavigationHandle(
+  explicit ServiceWorkerMainResourceHandle(
       ServiceWorkerContextWrapper* context_wrapper);
-  ~ServiceWorkerNavigationHandle();
+  ~ServiceWorkerMainResourceHandle();
 
   // Called after a ServiceWorkerProviderHost tied with |provider_info|
   // was pre-created for the navigation.
@@ -87,25 +85,25 @@
 
   bool has_provider_info() const { return !!provider_info_; }
 
-  ServiceWorkerNavigationHandleCore* core() { return core_; }
+  ServiceWorkerMainResourceHandleCore* core() { return core_; }
 
   const ServiceWorkerContextWrapper* context_wrapper() const {
     return context_wrapper_.get();
   }
 
-  base::WeakPtr<ServiceWorkerNavigationHandle> AsWeakPtr() {
+  base::WeakPtr<ServiceWorkerMainResourceHandle> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
 
  private:
   blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info_;
 
-  ServiceWorkerNavigationHandleCore* core_;
+  ServiceWorkerMainResourceHandleCore* core_;
   scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
-  base::WeakPtrFactory<ServiceWorkerNavigationHandle> weak_factory_{this};
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationHandle);
+  base::WeakPtrFactory<ServiceWorkerMainResourceHandle> weak_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMainResourceHandle);
 };
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
+#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_H_
diff --git a/content/browser/service_worker/service_worker_navigation_handle_core.cc b/content/browser/service_worker/service_worker_main_resource_handle_core.cc
similarity index 68%
rename from content/browser/service_worker/service_worker_navigation_handle_core.cc
rename to content/browser/service_worker/service_worker_main_resource_handle_core.cc
index e3602de..9bfc41f 100644
--- a/content/browser/service_worker/service_worker_navigation_handle_core.cc
+++ b/content/browser/service_worker/service_worker_main_resource_handle_core.cc
@@ -2,28 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/common/service_worker/service_worker_utils.h"
 
 namespace content {
 
-ServiceWorkerNavigationHandleCore::ServiceWorkerNavigationHandleCore(
-    base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle,
+ServiceWorkerMainResourceHandleCore::ServiceWorkerMainResourceHandleCore(
+    base::WeakPtr<ServiceWorkerMainResourceHandle> ui_handle,
     ServiceWorkerContextWrapper* context_wrapper)
     : context_wrapper_(context_wrapper), ui_handle_(ui_handle) {
-  // The ServiceWorkerNavigationHandleCore is created on the UI thread but
+  // The ServiceWorkerMainResourceHandleCore is created on the UI thread but
   // should only be accessed from the core thread afterwards.
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
-ServiceWorkerNavigationHandleCore::~ServiceWorkerNavigationHandleCore() {
+ServiceWorkerMainResourceHandleCore::~ServiceWorkerMainResourceHandleCore() {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
 }
 
-void ServiceWorkerNavigationHandleCore::OnBeginNavigationCommit(
+void ServiceWorkerMainResourceHandleCore::OnBeginNavigationCommit(
     int render_process_id,
     int render_frame_id,
     network::mojom::CrossOriginEmbedderPolicy cross_origin_embedder_policy) {
@@ -34,7 +34,7 @@
   }
 }
 
-void ServiceWorkerNavigationHandleCore::OnBeginWorkerCommit(
+void ServiceWorkerMainResourceHandleCore::OnBeginWorkerCommit(
     network::mojom::CrossOriginEmbedderPolicy cross_origin_embedder_policy) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   if (container_host_) {
diff --git a/content/browser/service_worker/service_worker_navigation_handle_core.h b/content/browser/service_worker/service_worker_main_resource_handle_core.h
similarity index 64%
rename from content/browser/service_worker/service_worker_navigation_handle_core.h
rename to content/browser/service_worker/service_worker_main_resource_handle_core.h
index 241fb72..0c68fe9d 100644
--- a/content/browser/service_worker/service_worker_navigation_handle_core.h
+++ b/content/browser/service_worker/service_worker_main_resource_handle_core.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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_CORE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_CORE_H_
 
 #include <memory>
 #include <utility>
@@ -19,24 +19,24 @@
 namespace content {
 
 class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 
 // This class is created on the UI thread, but should only be accessed from the
 // service worker core thread afterwards. It is the core thread pendant of
-// ServiceWorkerNavigationHandle. See the ServiceWorkerNavigationHandle header
-// for more details about the lifetime of both classes.
+// ServiceWorkerMainResourceHandle. See the ServiceWorkerMainResourceHandle
+// header for more details about the lifetime of both classes.
 //
-// TODO(crbug.com/824858): Merge this class into ServiceWorkerNavigationHandle
+// TODO(crbug.com/824858): Merge this class into ServiceWorkerMainResourceHandle
 // when the core thread moves to the UI thread.
-class CONTENT_EXPORT ServiceWorkerNavigationHandleCore {
+class CONTENT_EXPORT ServiceWorkerMainResourceHandleCore {
  public:
-  ServiceWorkerNavigationHandleCore(
-      base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle,
+  ServiceWorkerMainResourceHandleCore(
+      base::WeakPtr<ServiceWorkerMainResourceHandle> ui_handle,
       ServiceWorkerContextWrapper* context_wrapper);
-  ~ServiceWorkerNavigationHandleCore();
+  ~ServiceWorkerMainResourceHandleCore();
 
-  // Called by corresponding methods in ServiceWorkerNavigationHandle. See
-  // comments in the header of ServiceWorkerNavigationHandle for details.
+  // Called by corresponding methods in ServiceWorkerMainResourceHandle. See
+  // comments in the header of ServiceWorkerMainResourceHandle for details.
   void OnBeginNavigationCommit(
       int render_process_id,
       int render_frame_id,
@@ -66,20 +66,20 @@
     return interceptor_.get();
   }
 
-  base::WeakPtr<ServiceWorkerNavigationHandleCore> AsWeakPtr() {
+  base::WeakPtr<ServiceWorkerMainResourceHandleCore> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
 
  private:
   scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
-  base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle_;
+  base::WeakPtr<ServiceWorkerMainResourceHandle> ui_handle_;
   base::WeakPtr<ServiceWorkerContainerHost> container_host_;
   std::unique_ptr<ServiceWorkerControlleeRequestHandler> interceptor_;
-  base::WeakPtrFactory<ServiceWorkerNavigationHandleCore> weak_factory_{this};
+  base::WeakPtrFactory<ServiceWorkerMainResourceHandleCore> weak_factory_{this};
 
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationHandleCore);
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMainResourceHandleCore);
 };
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
+#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_MAIN_RESOURCE_HANDLE_CORE_H_
diff --git a/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc b/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc
index 61c0fa2..5666d13 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc
@@ -14,8 +14,8 @@
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
@@ -29,7 +29,7 @@
 // Core thread helpers
 
 void LoaderCallbackWrapperOnCoreThread(
-    ServiceWorkerNavigationHandleCore* handle_core,
+    ServiceWorkerMainResourceHandleCore* handle_core,
     base::WeakPtr<ServiceWorkerNavigationLoaderInterceptor> interceptor_on_ui,
     NavigationLoaderInterceptor::LoaderCallback loader_callback,
     SingleRequestURLLoaderFactory::RequestHandler handler) {
@@ -77,7 +77,7 @@
 // |interceptor_on_ui->LoaderCallbackWrapper()| on the UI thread.
 void MaybeCreateLoaderOnCoreThread(
     base::WeakPtr<ServiceWorkerNavigationLoaderInterceptor> interceptor_on_ui,
-    ServiceWorkerNavigationHandleCore* handle_core,
+    ServiceWorkerMainResourceHandleCore* handle_core,
     const ServiceWorkerNavigationLoaderInterceptorParams& params,
     mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost>
         host_receiver,
@@ -106,7 +106,7 @@
   if (!handle_core->container_host()) {
     // This is the initial request before redirects, so make the container host.
     // Its lifetime is tied to the |provider_info| in the
-    // ServiceWorkerNavigationHandle on the UI thread and which will be passed
+    // ServiceWorkerMainResourceHandle on the UI thread and which will be passed
     // to the renderer when the navigation commits.
     DCHECK(host_receiver);
     DCHECK(client_remote);
@@ -177,7 +177,7 @@
 ServiceWorkerNavigationLoaderInterceptor::
     ServiceWorkerNavigationLoaderInterceptor(
         const ServiceWorkerNavigationLoaderInterceptorParams& params,
-        base::WeakPtr<ServiceWorkerNavigationHandle> handle)
+        base::WeakPtr<ServiceWorkerMainResourceHandle> handle)
     : handle_(std::move(handle)), params_(params) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(handle_);
diff --git a/content/browser/service_worker/service_worker_navigation_loader_interceptor.h b/content/browser/service_worker/service_worker_navigation_loader_interceptor.h
index c1d6036..0f4b130a 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_interceptor.h
+++ b/content/browser/service_worker/service_worker_navigation_loader_interceptor.h
@@ -21,7 +21,7 @@
 
 namespace content {
 
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 
 struct ServiceWorkerNavigationLoaderInterceptorParams {
   // For all clients:
@@ -50,7 +50,7 @@
  public:
   ServiceWorkerNavigationLoaderInterceptor(
       const ServiceWorkerNavigationLoaderInterceptorParams& params,
-      base::WeakPtr<ServiceWorkerNavigationHandle> handle);
+      base::WeakPtr<ServiceWorkerMainResourceHandle> handle);
   ~ServiceWorkerNavigationLoaderInterceptor() override;
 
   // NavigationLoaderInterceptor overrides:
@@ -92,7 +92,7 @@
   // DedicatedWorkerHost or SharedWorkerHost which may be destroyed before
   // WorkerScriptLoader which owns |this|.
   // TODO(falken): Arrange things so |handle_| outlives |this| for workers too.
-  const base::WeakPtr<ServiceWorkerNavigationHandle> handle_;
+  const base::WeakPtr<ServiceWorkerMainResourceHandle> handle_;
 
   const ServiceWorkerNavigationLoaderInterceptorParams params_;
 
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index b31d4ea..b4a48fa 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -276,7 +276,8 @@
     for (std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator> it =
              context_->GetClientContainerHostIterator(
                  container_host->url().GetOrigin(),
-                 false /* include_reserved_clients */);
+                 false /* include_reserved_clients */,
+                 false /* include_back_forward_cached_clients */);
          !it->IsAtEnd(); it->Advance()) {
       if (container_host == it->GetContainerHost())
         return true;
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 309cff0c..073f003a 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -799,10 +799,14 @@
 void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
     ServiceWorkerRegistration* registration) {
   DCHECK(registration);
+  // Include bfcached clients because they need to have the correct
+  // information about the matching registrations if, e.g., claim() is called
+  // while they are in bfcache or after they are restored from bfcache.
   for (std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator> it =
            context_->GetClientContainerHostIterator(
                registration->scope().GetOrigin(),
-               true /* include_reserved_clients */);
+               true /* include_reserved_clients */,
+               true /* include_back_forward_cached_clients */);
        !it->IsAtEnd(); it->Advance()) {
     ServiceWorkerContainerHost* container_host = it->GetContainerHost();
     DCHECK(container_host->IsContainerForClient());
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index 3d2aa67..b4b875c 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -257,9 +257,12 @@
   // "For each service worker client client whose origin is the same as the
   //  service worker's origin:
   const bool include_reserved_clients = false;
+  // Include clients in BackForwardCache in order to evict them if needed.
+  const bool include_back_forward_cached_clients = true;
   for (std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator> it =
-           context_->GetClientContainerHostIterator(scope_.GetOrigin(),
-                                                    include_reserved_clients);
+           context_->GetClientContainerHostIterator(
+               scope_.GetOrigin(), include_reserved_clients,
+               include_back_forward_cached_clients);
        !it->IsAtEnd(); it->Advance()) {
     ServiceWorkerContainerHost* container_host = it->GetContainerHost();
     // "1. If client’s execution ready flag is unset or client’s discarded flag
@@ -284,6 +287,11 @@
     if (container_host->MatchRegistration() != this)
       continue;
 
+    // Evict the client in BackForwardCache.
+    if (container_host->IsInBackForwardCache())
+      container_host->EvictFromBackForwardCache(
+          BackForwardCacheMetrics::NotRestoredReason::kServiceWorkerClaim);
+
     // The remaining steps are performed here:
     container_host->ClaimedByRegistration(this);
   }
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc
index 305eb4f..b7b6f6cea 100644
--- a/content/browser/service_worker/service_worker_request_handler.cc
+++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -8,7 +8,7 @@
 
 #include "base/macros.h"
 #include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/service_worker/service_worker_navigation_loader_interceptor.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/public/common/origin_util.h"
@@ -35,7 +35,7 @@
 std::unique_ptr<NavigationLoaderInterceptor>
 ServiceWorkerRequestHandler::CreateForNavigation(
     const GURL& url,
-    base::WeakPtr<ServiceWorkerNavigationHandle> navigation_handle,
+    base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle,
     const NavigationRequestInfo& request_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -63,7 +63,7 @@
 ServiceWorkerRequestHandler::CreateForWorker(
     const network::ResourceRequest& resource_request,
     int process_id,
-    base::WeakPtr<ServiceWorkerNavigationHandle> navigation_handle) {
+    base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   auto resource_type =
diff --git a/content/browser/service_worker/service_worker_request_handler.h b/content/browser/service_worker/service_worker_request_handler.h
index 64294ae..9bc1d215 100644
--- a/content/browser/service_worker/service_worker_request_handler.h
+++ b/content/browser/service_worker/service_worker_request_handler.h
@@ -19,7 +19,7 @@
 
 namespace content {
 
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 struct NavigationRequestInfo;
 
 // Contains factory methods for creating the NavigationLoaderInterceptors for
@@ -32,7 +32,7 @@
   // navigation cannot use service workers. Called on the UI thread.
   static std::unique_ptr<NavigationLoaderInterceptor> CreateForNavigation(
       const GURL& url,
-      base::WeakPtr<ServiceWorkerNavigationHandle> navigation_handle,
+      base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle,
       const NavigationRequestInfo& request_info);
 
   // Returns a loader interceptor for a dedicated worker or shared worker. May
@@ -41,7 +41,7 @@
   static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorker(
       const network::ResourceRequest& resource_request,
       int process_id,
-      base::WeakPtr<ServiceWorkerNavigationHandle> navigation_handle);
+      base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestHandler);
diff --git a/content/browser/service_worker/service_worker_request_handler_unittest.cc b/content/browser/service_worker/service_worker_request_handler_unittest.cc
index e7b02aa..1bb432b5 100644
--- a/content/browser/service_worker/service_worker_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -14,7 +14,7 @@
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/common/navigation_params.mojom.h"
@@ -55,7 +55,7 @@
   void InitializeHandlerForNavigationSimpleTest(const std::string& url,
                                                 bool expected_handler_created) {
     auto navigation_handle =
-        std::make_unique<ServiceWorkerNavigationHandle>(context_wrapper());
+        std::make_unique<ServiceWorkerMainResourceHandle>(context_wrapper());
     GURL gurl(url);
     auto begin_params = mojom::BeginNavigationParams::New();
     begin_params->request_context_type =
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index dadcafb..56efbdb 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -132,6 +132,7 @@
       mojom::CommitNavigationParamsPtr commit_params,
       bool has_stale_copy_in_cache,
       int error_code,
+      const net::ResolveErrorInfo& resolve_error_info,
       const base::Optional<std::string>& error_page_content,
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loaders,
       CommitFailedNavigationCallback callback) override {
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 48cb1eb..228c8cb 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -95,7 +95,7 @@
 
   void OnInputEvent(const blink::WebInputEvent& event) override {
     events_received_.push_back(event.GetType());
-    event_ = event.Clone();
+    event_ = ui::WebInputEventTraits::Clone(event);
   }
 
   const std::vector<InputEventAckSource>& events_acked() {
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 8e1ab0e..d81f34d0 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -27,6 +27,7 @@
 #include "base/time/default_clock.h"
 #include "build/build_config.h"
 #include "components/leveldb_proto/public/proto_database_provider.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/browser/background_fetch/background_fetch_context.h"
 #include "content/browser/blob_storage/blob_registry_wrapper.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -1461,6 +1462,25 @@
   return lock_manager_.get();
 }
 
+storage::mojom::IndexedDBControl& StoragePartitionImpl::GetIndexedDBControl() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(
+      !(indexed_db_control_.is_bound() && !indexed_db_control_.is_connected()))
+      << "Rebinding is not supported yet.";
+
+  if (indexed_db_control_.is_bound())
+    return *indexed_db_control_;
+
+  IndexedDBContextImpl* idb_context = GetIndexedDBContext();
+  idb_context->IDBTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&IndexedDBContextImpl::Bind,
+                     base::WrapRefCounted(idb_context),
+                     indexed_db_control_.BindNewPipeAndPassReceiver()));
+
+  return *indexed_db_control_;
+}
+
 IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() {
   DCHECK(initialized_);
   return indexed_db_context_.get();
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 1809fac..ec2b6698 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -17,6 +17,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/process/process_handle.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/background_sync/background_sync_context_impl.h"
 #include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
@@ -41,6 +42,7 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/shared_remote.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/network_service.mojom.h"
@@ -129,6 +131,7 @@
   DOMStorageContextWrapper* GetDOMStorageContext() override;
   IdleManager* GetIdleManager();
   LockManager* GetLockManager();  // override; TODO: Add to interface
+  storage::mojom::IndexedDBControl& GetIndexedDBControl() override;
   IndexedDBContextImpl* GetIndexedDBContext() override;
   NativeFileSystemEntryFactory* GetNativeFileSystemEntryFactory() override;
   CacheStorageContextImpl* GetCacheStorageContext() override;
@@ -431,6 +434,7 @@
   scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
   std::unique_ptr<IdleManager> idle_manager_;
   scoped_refptr<LockManager> lock_manager_;
+  mojo::Remote<storage::mojom::IndexedDBControl> indexed_db_control_;
   scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
   scoped_refptr<CacheStorageContextImpl> cache_storage_context_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 2ade6f6..ec0c370 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1468,6 +1468,10 @@
                context.transformed_pt.value(), context.screen_pt, key_modifiers,
                /*drop_allowed=*/false);
     }
+
+    // The drop not being continued requires this to cleanup the drag data.
+    OnDragExited();
+
     return;
   }
 
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 781c0f49..ad25476 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -656,6 +656,7 @@
   run_loop.Run();
 
   EXPECT_TRUE(drag_dest_delegate_.GetOnDropCalled());
+  EXPECT_FALSE(drag_dest_delegate_.GetOnDragLeaveCalled());
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OnPerformDrop_DeepScanBad) {
@@ -689,6 +690,7 @@
   run_loop.Run();
 
   EXPECT_FALSE(drag_dest_delegate_.GetOnDropCalled());
+  EXPECT_TRUE(drag_dest_delegate_.GetOnDragLeaveCalled());
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
diff --git a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index 4f19f7e..a0ed484 100644
--- a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -104,6 +104,13 @@
 
 IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
                        VerifyCanvasCaptureWebGLFrames) {
+#if defined(OS_ANDROID)
+  // TODO(ericrk): fails on Pixel 2 Skia Renderer Vulkan after shared image
+  // changes. See https://crbug.com/1039232
+  if (base::SysInfo::HardwareModelName() == "Pixel 2") {
+    return;
+  }
+#endif
   MakeTypicalCall("testCanvasCapture(drawWebGL);", kCanvasCaptureTestHtmlFile);
 }
 
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index cf37613c..f8fbae0 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -14,7 +14,7 @@
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/interface_provider_filtering.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/service_worker/service_worker_object_host.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_params_helper.h"
@@ -180,7 +180,7 @@
   // factories be used for subresource loading on the worker.
   file_url_support_ = request_initiator_origin.scheme() == url::kFileScheme;
 
-  service_worker_handle_ = std::make_unique<ServiceWorkerNavigationHandle>(
+  service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
       storage_partition_impl->GetServiceWorkerContext());
 
   WorkerScriptFetchInitiator::Start(
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h
index d224846..fbdbed8 100644
--- a/content/browser/worker_host/dedicated_worker_host.h
+++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -34,7 +34,7 @@
 
 namespace content {
 
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class ServiceWorkerObjectHost;
 class StoragePartitionImpl;
 
@@ -170,7 +170,7 @@
   // starting or running.
   mojo::Remote<blink::mojom::DedicatedWorkerHostFactoryClient> client_;
 
-  std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
 
   BrowserInterfaceBrokerImpl<DedicatedWorkerHost, const url::Origin&> broker_{
       this};
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index a7026c2..bc4f340 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -16,7 +16,7 @@
 #include "content/browser/devtools/shared_worker_devtools_manager.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/interface_provider_filtering.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/service_worker/service_worker_object_host.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_params_helper.h"
@@ -448,7 +448,7 @@
 }
 
 void SharedWorkerHost::SetServiceWorkerHandle(
-    std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle) {
+    std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   service_worker_handle_ = std::move(service_worker_handle);
 }
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h
index 5f59cead..9c280cd 100644
--- a/content/browser/worker_host/shared_worker_host.h
+++ b/content/browser/worker_host/shared_worker_host.h
@@ -49,7 +49,7 @@
 namespace content {
 
 class AppCacheNavigationHandle;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class ServiceWorkerObjectHost;
 class SharedWorkerContentSettingsProxyImpl;
 class SharedWorkerServiceImpl;
@@ -114,7 +114,7 @@
   void SetAppCacheHandle(
       std::unique_ptr<AppCacheNavigationHandle> appcache_handle);
   void SetServiceWorkerHandle(
-      std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle);
+      std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle);
 
   // Removes all clients whose RenderFrameHost has been destroyed before the
   // shared worker was started.
@@ -222,7 +222,7 @@
   // renderer after main script loading finishes.
   std::unique_ptr<AppCacheNavigationHandle> appcache_handle_;
 
-  std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
 
   // Indicates if Start() was invoked on this instance.
   bool started_ = false;
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc
index 5617eb9..fb26e20 100644
--- a/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -14,7 +14,7 @@
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/navigation_subresource_loader_params.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/worker_host/mock_shared_worker.h"
 #include "content/browser/worker_host/shared_worker_connector_impl.h"
 #include "content/browser/worker_host/shared_worker_service_impl.h"
@@ -99,7 +99,7 @@
 
     // Set up for service worker.
     auto service_worker_handle =
-        std::make_unique<ServiceWorkerNavigationHandle>(
+        std::make_unique<ServiceWorkerMainResourceHandle>(
             helper_->context_wrapper());
     mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer>
         client_remote;
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 62d338a..f7e7a2d 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -18,7 +18,7 @@
 #include "base/task/post_task.h"
 #include "content/browser/appcache/appcache_navigation_handle.h"
 #include "content/browser/loader/file_url_loader_factory.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -273,8 +273,9 @@
       appcache_handle->host()->GetWeakPtr();
   host->SetAppCacheHandle(std::move(appcache_handle));
 
-  auto service_worker_handle = std::make_unique<ServiceWorkerNavigationHandle>(
-      storage_partition_->GetServiceWorkerContext());
+  auto service_worker_handle =
+      std::make_unique<ServiceWorkerMainResourceHandle>(
+          storage_partition_->GetServiceWorkerContext());
   auto* service_worker_handle_raw = service_worker_handle.get();
   host->SetServiceWorkerHandle(std::move(service_worker_handle));
 
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index e001da7..c3d4948 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -21,8 +21,8 @@
 #include "content/browser/loader/file_url_loader_factory.h"
 #include "content/browser/navigation_subresource_loader_params.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_params_helper.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -66,7 +66,7 @@
         outside_fetch_client_settings_object,
     ResourceType resource_type,
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-    ServiceWorkerNavigationHandle* service_worker_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     base::WeakPtr<AppCacheHost> appcache_host,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override,
@@ -282,7 +282,7 @@
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
         subresource_loader_factories,
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-    ServiceWorkerNavigationHandle* service_worker_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     base::WeakPtr<AppCacheHost> appcache_host,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override,
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h
index 1bd74a3..7efd593 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.h
+++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -36,7 +36,7 @@
 class BrowserContext;
 class RenderFrameHost;
 class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class ServiceWorkerObjectHost;
 class StoragePartitionImpl;
 struct SubresourceLoaderParams;
@@ -68,7 +68,7 @@
           outside_fetch_client_settings_object,
       ResourceType resource_type,
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       base::WeakPtr<AppCacheHost> appcache_host,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
       scoped_refptr<network::SharedURLLoaderFactory>
@@ -106,7 +106,7 @@
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
           subresource_loader_factories,
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       base::WeakPtr<AppCacheHost> appcache_host,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
       scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index a6a5ab6..b7a9a714 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -8,8 +8,8 @@
 #include "base/task/post_task.h"
 #include "content/browser/appcache/appcache_request_handler.h"
 #include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/browser/service_worker/service_worker_request_handler.h"
 #include "content/browser/worker_host/worker_script_fetch_initiator.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -26,7 +26,7 @@
     uint32_t options,
     const network::ResourceRequest& resource_request,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
-    base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle,
+    base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle,
     base::WeakPtr<AppCacheHost> appcache_host,
     const BrowserContextGetter& browser_context_getter,
     scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h
index a6aa257..b2ceded 100644
--- a/content/browser/worker_host/worker_script_loader.h
+++ b/content/browser/worker_host/worker_script_loader.h
@@ -36,7 +36,7 @@
 class BrowserContext;
 class NavigationLoaderInterceptor;
 class ResourceContext;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 
 // The URLLoader for loading a shared worker script. Only used for the main
 // script request.
@@ -72,7 +72,7 @@
       uint32_t options,
       const network::ResourceRequest& resource_request,
       mojo::PendingRemote<network::mojom::URLLoaderClient> client,
-      base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle,
+      base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle,
       base::WeakPtr<AppCacheHost> appcache_host,
       const BrowserContextGetter& browser_context_getter,
       scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
@@ -145,7 +145,7 @@
   const uint32_t options_;
   network::ResourceRequest resource_request_;
   mojo::Remote<network::mojom::URLLoaderClient> client_;
-  base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle_;
   BrowserContextGetter browser_context_getter_;
   scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory_;
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc
index a38d468f..7d5e5a1 100644
--- a/content/browser/worker_host/worker_script_loader_factory.cc
+++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -7,8 +7,8 @@
 #include <memory>
 
 #include "base/feature_list.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/worker_host/worker_script_fetch_initiator.h"
@@ -22,7 +22,7 @@
 
 WorkerScriptLoaderFactory::WorkerScriptLoaderFactory(
     int process_id,
-    ServiceWorkerNavigationHandle* service_worker_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     base::WeakPtr<AppCacheHost> appcache_host,
     const BrowserContextGetter& browser_context_getter,
     scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h
index 9e7766e9..89ab86b 100644
--- a/content/browser/worker_host/worker_script_loader_factory.h
+++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -20,7 +20,7 @@
 
 class AppCacheHost;
 class BrowserContext;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerMainResourceHandle;
 class ResourceContext;
 class WorkerScriptLoader;
 
@@ -48,7 +48,7 @@
   // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
   WorkerScriptLoaderFactory(
       int process_id,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       base::WeakPtr<AppCacheHost> appcache_host,
       const BrowserContextGetter& browser_context_getter,
       scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
@@ -71,7 +71,7 @@
 
  private:
   const int process_id_;
-  base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle_;
   base::WeakPtr<AppCacheHost> appcache_host_;
   BrowserContextGetter browser_context_getter_;
   scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index 802f5c2..5801338 100644
--- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -10,8 +10,8 @@
 #include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle.h"
+#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/test/fake_network_url_loader_factory.h"
 #include "net/base/network_isolation_key.h"
@@ -56,7 +56,7 @@
         network::SharedURLLoaderFactory::Create(std::move(info));
 
     // Set up a service worker host for the shared worker.
-    service_worker_handle_ = std::make_unique<ServiceWorkerNavigationHandle>(
+    service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
         helper_->context_wrapper());
   }
 
@@ -86,7 +86,7 @@
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
   std::unique_ptr<FakeNetworkURLLoaderFactory> network_loader_factory_instance_;
   scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
-  std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_;
+  std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
 
   WorkerScriptLoaderFactory::BrowserContextGetter browser_context_getter_;
 };
diff --git a/content/common/input/event_with_latency_info.h b/content/common/input/event_with_latency_info.h
index 58e8b8ca..e61aa65 100644
--- a/content/common/input/event_with_latency_info.h
+++ b/content/common/input/event_with_latency_info.h
@@ -41,6 +41,9 @@
     if (other.event.GetType() != event.GetType())
       return false;
 
+    DCHECK_EQ(sizeof(T), event.size());
+    DCHECK_EQ(sizeof(T), other.event.size());
+
     return ui::CanCoalesce(other.event, event);
   }
 
diff --git a/content/common/input/input_event.cc b/content/common/input/input_event.cc
index 4e11e69a..5204dde 100644
--- a/content/common/input/input_event.cc
+++ b/content/common/input/input_event.cc
@@ -16,7 +16,8 @@
 
 InputEvent::InputEvent(const blink::WebInputEvent& web_event,
                        const ui::LatencyInfo& latency_info)
-    : web_event(web_event.Clone()), latency_info(latency_info) {}
+    : web_event(ui::WebInputEventTraits::Clone(web_event)),
+      latency_info(latency_info) {}
 
 InputEvent::~InputEvent() {}
 
diff --git a/content/common/navigation_client.mojom b/content/common/navigation_client.mojom
index d96c190..bd561f89 100644
--- a/content/common/navigation_client.mojom
+++ b/content/common/navigation_client.mojom
@@ -4,6 +4,7 @@
 
 module content.mojom;
 
+import "services/network/public/mojom/host_resolver.mojom";
 import "services/network/public/mojom/url_response_head.mojom";
 import "services/network/public/mojom/url_loader.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
@@ -82,6 +83,7 @@
       CommitNavigationParams request_params,
       bool has_stale_copy_in_cache,
       int32 error_code,
+      network.mojom.ResolveErrorInfo resolve_error_info,
       string? error_page_content,
       blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories)
       => (DidCommitProvisionalLoadParams params,
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index a338dc0f..e910fd21 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -105,6 +105,13 @@
       error_message->append("') was received when fetching the script.");
       return false;
     }
+
+    if (max_scope.GetOrigin() != script_url.GetOrigin()) {
+      *error_message = "A cross-origin Service-Worker-Allowed header value ('";
+      error_message->append(*service_worker_allowed_header_value);
+      error_message->append("') was received when fetching the script.");
+      return false;
+    }
     max_scope_string = max_scope.path();
   } else {
     max_scope_string = script_url.GetWithoutFilename().path();
diff --git a/content/common/service_worker/service_worker_utils_unittest.cc b/content/common/service_worker/service_worker_utils_unittest.cc
index f19e682..1b0cc91 100644
--- a/content/common/service_worker/service_worker_utils_unittest.cc
+++ b/content/common/service_worker/service_worker_utils_unittest.cc
@@ -402,6 +402,14 @@
   EXPECT_TRUE(IsPathRestrictionSatisfiedWithServiceWorkerAllowedHeader(
       GURL("http://example.com/sw.js/hi"), GURL("http://example.com/sw.js"),
       ""));
+
+  // Cross origin header value is not accepted.
+  EXPECT_FALSE(IsPathRestrictionSatisfiedWithServiceWorkerAllowedHeader(
+      GURL("http://example.com/"), GURL("http://example.com/sw.js"),
+      "http://other.com/"));
+  EXPECT_FALSE(IsPathRestrictionSatisfiedWithServiceWorkerAllowedHeader(
+      GURL("http://example.com/foo/"), GURL("http://example.com/bar/sw.js"),
+      "http://other.com/foo/"));
 }
 
 TEST(ServiceWorkerUtilsTest, AllOriginsMatchAndCanAccessServiceWorkers) {
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index ec1ed91..53027c5a 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -414,6 +414,7 @@
   public_deps = [
     "//build:chromecast_buildflags",
     "//components/download/public/common:public",
+    "//components/services/storage/public/mojom",
     "//content/public/common:common_sources",
     "//ipc",
     "//media/mojo/mojom:remoting",
diff --git a/content/public/browser/DEPS b/content/public/browser/DEPS
index e61bb1d..93d7361 100644
--- a/content/public/browser/DEPS
+++ b/content/public/browser/DEPS
@@ -2,6 +2,7 @@
   # components/download are needed for providing the download feature.
   # TODO(qinmin): move it to services/download when download becomes a service.
   "+components/download/public/common",
+  "+components/services/storage/public",
   "+components/viz/common",
   "+components/viz/host",
   "+device/fido",
diff --git a/content/public/browser/indexed_db_context.h b/content/public/browser/indexed_db_context.h
index b4814d7..8e0a2f78 100644
--- a/content/public/browser/indexed_db_context.h
+++ b/content/public/browser/indexed_db_context.h
@@ -24,8 +24,6 @@
 
 namespace content {
 
-struct StorageUsageInfo;
-
 // Represents the per-BrowserContext IndexedDB data.
 // Call these methods only via the exposed IDBTaskRunner.
 // Refcounted because this class is used throughout the codebase on different
@@ -36,9 +34,6 @@
   // Only call the below methods by posting to this IDBTaskRunner.
   virtual base::SequencedTaskRunner* IDBTaskRunner() = 0;
 
-  // Methods used in response to QuotaManager requests.
-  virtual std::vector<StorageUsageInfo> GetAllOriginsInfo() = 0;
-
   // Deletes all indexed db files for the given origin.
   virtual void DeleteForOrigin(const url::Origin& origin) = 0;
 
@@ -56,9 +51,6 @@
   // Disables the exit-time deletion of session-only data.
   virtual void SetForceKeepSessionState() = 0;
 
-  // Helper function for posting IO tasks to.
-  virtual base::SequencedTaskRunner* IOTaskRunner() = 0;
-
  protected:
   friend class base::RefCountedDeleteOnSequence<IndexedDBContext>;
   friend class base::DeleteHelper<IndexedDBContext>;
@@ -67,7 +59,7 @@
       : base::RefCountedDeleteOnSequence<IndexedDBContext>(
             std::move(owning_task_runner)) {}
 
-  virtual ~IndexedDBContext() {}
+  virtual ~IndexedDBContext() = default;
 };
 
 }  // namespace content
diff --git a/content/public/browser/native_web_keyboard_event.h b/content/public/browser/native_web_keyboard_event.h
index 8498d45..7b10a74 100644
--- a/content/public/browser/native_web_keyboard_event.h
+++ b/content/public/browser/native_web_keyboard_event.h
@@ -57,7 +57,7 @@
 #endif
 
   NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event);
-  ~NativeWebKeyboardEvent() override;
+  ~NativeWebKeyboardEvent();
 
   NativeWebKeyboardEvent& operator=(const NativeWebKeyboardEvent& event);
 
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index 0e68e34..a0db8a9 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -13,6 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/time/time.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom-forward.h"
 #include "content/common/content_export.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/cookie_manager.mojom-forward.h"
@@ -125,6 +126,7 @@
   virtual storage::FileSystemContext* GetFileSystemContext() = 0;
   virtual storage::DatabaseTracker* GetDatabaseTracker() = 0;
   virtual DOMStorageContext* GetDOMStorageContext() = 0;
+  virtual storage::mojom::IndexedDBControl& GetIndexedDBControl() = 0;
   virtual IndexedDBContext* GetIndexedDBContext() = 0;
   virtual NativeFileSystemEntryFactory* GetNativeFileSystemEntryFactory() = 0;
   virtual ServiceWorkerContext* GetServiceWorkerContext() = 0;
diff --git a/content/public/test/DEPS b/content/public/test/DEPS
index b6ef2b0..a21da40 100644
--- a/content/public/test/DEPS
+++ b/content/public/test/DEPS
@@ -4,6 +4,7 @@
   "+components/discardable_memory/service",
   "+components/download/public/common",
   "+components/leveldb_proto/public",
+  "+components/services/storage/public",
   "+components/viz/common",
   "+components/viz/host",
   "+components/viz/service",
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc
index 76c0711..79cf5ad 100644
--- a/content/public/test/test_launcher.cc
+++ b/content/public/test/test_launcher.cc
@@ -116,7 +116,11 @@
           "    Sets the total number of shards to N.\n"
           "\n"
           "  --test-launcher-shard-index=N\n"
-          "    Sets the shard index to run to N (from 0 to TOTAL - 1).\n");
+          "    Sets the shard index to run to N (from 0 to TOTAL - 1).\n"
+          "\n"
+          "  --test-launcher-print-temp-leaks\n"
+          "    Prints information about leaked files and/or directories in\n"
+          "    child process's temporary directories (Windows and macOS).\n");
 }
 
 // Implementation of base::TestLauncherDelegate. This is also a test launcher,
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc
index 743ec3c..174c37d 100644
--- a/content/public/test/test_storage_partition.cc
+++ b/content/public/test/test_storage_partition.cc
@@ -77,6 +77,14 @@
   return dom_storage_context_;
 }
 
+storage::mojom::IndexedDBControl& TestStoragePartition::GetIndexedDBControl() {
+  // Bind and throw away the receiver. If testing is required, then add a method
+  // to set the remote.
+  if (!indexed_db_control_.is_bound())
+    ignore_result(indexed_db_control_.BindNewPipeAndPassReceiver());
+  return *indexed_db_control_;
+}
+
 IndexedDBContext* TestStoragePartition::GetIndexedDBContext() {
   return indexed_db_context_;
 }
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h
index 2be72f1d5..30f041f3 100644
--- a/content/public/test/test_storage_partition.h
+++ b/content/public/test/test_storage_partition.h
@@ -8,7 +8,9 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/public/browser/storage_partition.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace leveldb_proto {
 class ProtoDatabaseProvider;
@@ -104,6 +106,8 @@
   }
   DOMStorageContext* GetDOMStorageContext() override;
 
+  storage::mojom::IndexedDBControl& GetIndexedDBControl() override;
+
   void set_indexed_db_context(IndexedDBContext* context) {
     indexed_db_context_ = context;
   }
@@ -212,6 +216,7 @@
   storage::FileSystemContext* file_system_context_ = nullptr;
   storage::DatabaseTracker* database_tracker_ = nullptr;
   DOMStorageContext* dom_storage_context_ = nullptr;
+  mojo::Remote<storage::mojom::IndexedDBControl> indexed_db_control_;
   IndexedDBContext* indexed_db_context_ = nullptr;
   ServiceWorkerContext* service_worker_context_ = nullptr;
   SharedWorkerService* shared_worker_service_ = nullptr;
diff --git a/content/renderer/input/input_event_prediction.cc b/content/renderer/input/input_event_prediction.cc
index b8a7947..bd43bcb 100644
--- a/content/renderer/input/input_event_prediction.cc
+++ b/content/renderer/input/input_event_prediction.cc
@@ -168,7 +168,8 @@
       last_event_timestamp_ + mouse_predictor_->MaxPredictionTime();
   bool success = true;
   while (success) {
-    ui::WebScopedInputEvent predicted_event = coalesced_event.Event().Clone();
+    ui::WebScopedInputEvent predicted_event =
+        ui::WebInputEventTraits::Clone(coalesced_event.Event());
     success = false;
     if (predicted_event->GetType() == WebInputEvent::kTouchMove) {
       WebTouchEvent& touch_event =
diff --git a/content/renderer/input/main_thread_event_queue_unittest.cc b/content/renderer/input/main_thread_event_queue_unittest.cc
index 299833e0..35a467c 100644
--- a/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 
 #include <new>
-#include <tuple>
 #include <utility>
 #include <vector>
 
@@ -198,8 +197,8 @@
   void HandleEvent(WebInputEvent& event, InputEventAckState ack_result) {
     base::AutoReset<bool> in_handle_event(&handler_callback_->handling_event_,
                                           true);
-    queue_->HandleEvent(event.Clone(), ui::LatencyInfo(),
-                        DISPATCH_TYPE_BLOCKING, ack_result,
+    queue_->HandleEvent(ui::WebInputEventTraits::Clone(event),
+                        ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING, ack_result,
                         handler_callback_->GetCallback());
   }
 
@@ -355,6 +354,8 @@
   }
 
   {
+    EXPECT_EQ(kEvents[0].size(),
+              handled_tasks_.at(0)->taskAsEvent()->Event().size());
     EXPECT_EQ(kEvents[0].GetType(),
               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
     const WebMouseWheelEvent* last_wheel_event =
@@ -445,6 +446,8 @@
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
 
+  EXPECT_EQ(kEvents[0].size(),
+            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[0].GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
@@ -461,6 +464,8 @@
     EXPECT_TRUE(Equal(kEvents[0], *coalesced_touch_event));
   }
 
+  EXPECT_EQ(kEvents[1].size(),
+            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[1].GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   last_touch_event = static_cast<const WebTouchEvent*>(
@@ -477,6 +482,8 @@
     EXPECT_TRUE(Equal(kEvents[1], *coalesced_touch_event));
   }
 
+  EXPECT_EQ(kEvents[2].size(),
+            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[2].GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   last_touch_event = static_cast<const WebTouchEvent*>(
@@ -595,6 +602,8 @@
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
   {
+    EXPECT_EQ(kWheelEvents[0].size(),
+              handled_tasks_.at(0)->taskAsEvent()->Event().size());
     EXPECT_EQ(kWheelEvents[0].GetType(),
               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
     const WebMouseWheelEvent* last_wheel_event =
@@ -609,6 +618,8 @@
     EXPECT_TRUE(Equal(coalesced_event, *last_wheel_event));
   }
   {
+    EXPECT_EQ(kTouchEvents[0].size(),
+              handled_tasks_.at(1)->taskAsEvent()->Event().size());
     EXPECT_EQ(kTouchEvents[0].GetType(),
               handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
     const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
@@ -988,6 +999,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(1u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
@@ -1007,6 +1020,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
@@ -1025,6 +1040,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(2)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1041,6 +1058,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(4u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(3)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1067,6 +1086,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(1u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1084,6 +1105,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1101,6 +1124,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(2)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1118,6 +1143,8 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(4u, handled_tasks_.size());
+  EXPECT_EQ(kEvents.size(),
+            handled_tasks_.at(3)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
diff --git a/content/renderer/input/widget_input_handler_manager.cc b/content/renderer/input/widget_input_handler_manager.cc
index eafde289..21a11e3 100644
--- a/content/renderer/input/widget_input_handler_manager.cc
+++ b/content/renderer/input/widget_input_handler_manager.cc
@@ -258,7 +258,8 @@
   blink::WebGestureEvent scroll_begin =
       ui::ScrollBeginFromScrollUpdate(update_event);
 
-  DispatchNonBlockingEventToMainThread(scroll_begin.Clone(), ui::LatencyInfo());
+  DispatchNonBlockingEventToMainThread(
+      ui::WebInputEventTraits::Clone(scroll_begin), ui::LatencyInfo());
 }
 
 void WidgetInputHandlerManager::SetWhiteListedTouchAction(
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index 7b6a1d4..f7d86a0 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -224,6 +224,7 @@
   request_completed_ = true;
   response_->error_code = status.error_code;
   response_->extended_error_code = status.extended_error_code;
+  response_->resolve_error_info = status.resolve_error_info;
   response_->cors_error = status.cors_error_status;
   response_->head->encoded_data_length = status.encoded_data_length;
   response_->head->encoded_body_length = status.encoded_body_length;
diff --git a/content/renderer/loader/sync_load_response.h b/content/renderer/loader/sync_load_response.h
index d052bd4..6435a957 100644
--- a/content/renderer/loader/sync_load_response.h
+++ b/content/renderer/loader/sync_load_response.h
@@ -9,6 +9,7 @@
 
 #include "base/optional.h"
 #include "content/common/content_export.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/mojom/url_loader.mojom-forward.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
@@ -40,6 +41,9 @@
   // The response extended error code.
   int extended_error_code = 0;
 
+  // Detailed host resolution error information.
+  net::ResolveErrorInfo resolve_error_info;
+
   // Optional CORS error details.
   base::Optional<network::CorsErrorStatus> cors_error;
 
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index cde88b5..8891a62 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -1141,7 +1141,7 @@
   if (status.cors_error_status)
     return WebURLError(*status.cors_error_status, has_copy_in_cache, url);
   return WebURLError(status.error_code, status.extended_error_code,
-                     has_copy_in_cache,
+                     status.resolve_error_info, has_copy_in_cache,
                      WebURLError::IsWebSecurityViolation::kFalse, url);
 }
 
@@ -1178,6 +1178,7 @@
               ? WebURLError::IsWebSecurityViolation::kTrue
               : WebURLError::IsWebSecurityViolation::kFalse;
       error = WebURLError(error_code, sync_load_response.extended_error_code,
+                          sync_load_response.resolve_error_info,
                           WebURLError::HasCopyInCache::kFalse,
                           is_web_security_violation, final_url);
     }
diff --git a/content/renderer/navigation_client.cc b/content/renderer/navigation_client.cc
index 0a2da67e..c86b9f7 100644
--- a/content/renderer/navigation_client.cc
+++ b/content/renderer/navigation_client.cc
@@ -50,14 +50,15 @@
     mojom::CommitNavigationParamsPtr commit_params,
     bool has_stale_copy_in_cache,
     int error_code,
+    const net::ResolveErrorInfo& resolve_error_info,
     const base::Optional<std::string>& error_page_content,
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loaders,
     CommitFailedNavigationCallback callback) {
   ResetDisconnectionHandler();
   render_frame_->CommitFailedNavigation(
       std::move(common_params), std::move(commit_params),
-      has_stale_copy_in_cache, error_code, error_page_content,
-      std::move(subresource_loaders), std::move(callback));
+      has_stale_copy_in_cache, error_code, resolve_error_info,
+      error_page_content, std::move(subresource_loaders), std::move(callback));
 }
 
 void NavigationClient::Bind(
diff --git a/content/renderer/navigation_client.h b/content/renderer/navigation_client.h
index f865d642..749c04b 100644
--- a/content/renderer/navigation_client.h
+++ b/content/renderer/navigation_client.h
@@ -40,6 +40,7 @@
       mojom::CommitNavigationParamsPtr commit_params,
       bool has_stale_copy_in_cache,
       int error_code,
+      const net::ResolveErrorInfo& resolve_error_info,
       const base::Optional<std::string>& error_page_content,
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loaders,
       CommitFailedNavigationCallback callback) override;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 24c6fd2..4587c16 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3513,6 +3513,7 @@
     mojom::CommitNavigationParamsPtr commit_params,
     bool has_stale_copy_in_cache,
     int error_code,
+    net::ResolveErrorInfo resolve_error_info,
     const base::Optional<std::string>& error_page_content,
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
         subresource_loader_factories,
@@ -3543,7 +3544,7 @@
 
   // Send the provisional load failure.
   WebURLError error(
-      error_code, 0,
+      error_code, 0, resolve_error_info,
       has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue
                               : WebURLError::HasCopyInCache::kFalse,
       WebURLError::IsWebSecurityViolation::kFalse, common_params->url);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 8c865e0..00f31f4 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -581,6 +581,7 @@
       mojom::CommitNavigationParamsPtr commit_params,
       bool has_stale_copy_in_cache,
       int error_code,
+      net::ResolveErrorInfo resolve_error_info,
       const base::Optional<std::string>& error_page_content,
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
           subresource_loader_factories,
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index c86f6bda..b065ec1 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -63,6 +63,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/net_errors.h"
 #include "net/cert/cert_status_flags.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -2112,7 +2113,8 @@
   TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
   main_frame->NavigateWithError(
       std::move(common_params), CreateCommitNavigationParams(),
-      net::ERR_FILE_NOT_FOUND, "A suffusion of yellow.");
+      net::ERR_FILE_NOT_FOUND, net::ResolveErrorInfo(net::OK),
+      "A suffusion of yellow.");
 
   const int kMaxOutputCharacters = 22;
   EXPECT_EQ("", WebFrameContentDumper::DumpWebViewAsText(view()->GetWebView(),
@@ -2134,7 +2136,8 @@
   TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
   main_frame->NavigateWithError(
       std::move(common_params), CreateCommitNavigationParams(),
-      net::ERR_FILE_NOT_FOUND, "A suffusion of yellow.");
+      net::ERR_FILE_NOT_FOUND, net::ResolveErrorInfo(net::OK),
+      "A suffusion of yellow.");
 
   // The error page itself is loaded asynchronously.
   FrameLoadWaiter(main_frame).Wait();
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 17e84479..0e06fa8f 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -568,14 +568,14 @@
       switches::kEnableWebRtcStunOrigin);
 }
 
-base::Optional<std::string>
+base::Optional<blink::WebString>
 RendererBlinkPlatformImpl::WebRtcStunProbeTrialParameter() {
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
   if (!cmd_line->HasSwitch(switches::kWebRtcStunProbeTrialParameter))
     return base::nullopt;
 
-  return cmd_line->GetSwitchValueASCII(
-      switches::kWebRtcStunProbeTrialParameter);
+  return blink::WebString::FromASCII(
+      cmd_line->GetSwitchValueASCII(switches::kWebRtcStunProbeTrialParameter));
 }
 
 media::MediaPermission* RendererBlinkPlatformImpl::GetWebRTCMediaPermission(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index edbf232..096cd16 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -137,7 +137,7 @@
   bool UsesFakeCodecForPeerConnection() override;
   bool IsWebRtcEncryptionEnabled() override;
   bool IsWebRtcStunOriginEnabled() override;
-  base::Optional<std::string> WebRtcStunProbeTrialParameter() override;
+  base::Optional<blink::WebString> WebRtcStunProbeTrialParameter() override;
   media::MediaPermission* GetWebRTCMediaPermission(
       blink::WebLocalFrame* web_frame) override;
   void GetWebRTCRendererPreferences(blink::WebLocalFrame* web_frame,
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc
index 858af96..676e8fe 100644
--- a/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -61,7 +61,6 @@
 
 }  // namespace
 
-// For service worker clients.
 ServiceWorkerProviderContext::ServiceWorkerProviderContext(
     blink::mojom::ServiceWorkerProviderType provider_type,
     mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainer>
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index dfcea04bb..79879df 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -341,6 +341,7 @@
 
   public_deps = [
     "//components/download/public/common:test_support",
+    "//components/services/storage/public/mojom",
     "//content/public/app:both",
     "//content/public/browser",
     "//content/public/common",
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt
index 17f6c15f..0066096 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt
@@ -21,26 +21,25 @@
 ++++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++AXButton AXRoleDescription='button' AXDescription='Show previous month'
 ++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++AXButton AXRoleDescription='button' AXDescription='Today'
-++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++AXButton AXRoleDescription='button' AXDescription='Show next month'
 ++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++AXTable AXRoleDescription='table' AXDescription='Sun Mon Tue Wed Thu Fri Sat'
+++++++++++++AXTable AXRoleDescription='table' AXDescription='S M T W T F S Today'
 ++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Sun'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='S'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Mon'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='M'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Tue'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='T'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Wed'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='W'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Thu'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='T'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Fri'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='F'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Sat'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='S'
 ++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++++++AXGroup AXRoleDescription='group'
+++++++++++++++AXButton AXRoleDescription='button' AXDescription='Today'
 ++++++++++++++AXGroup AXRoleDescription='group'
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-mac.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-mac.txt
index 146e097..9e429dd 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-mac.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-mac.txt
@@ -45,26 +45,25 @@
 ++++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++AXButton AXRoleDescription='button' AXDescription='Show previous month'
 ++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++AXButton AXRoleDescription='button' AXDescription='Today'
-++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++AXButton AXRoleDescription='button' AXDescription='Show next month'
 ++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++AXTable AXRoleDescription='table' AXDescription='Sun Mon Tue Wed Thu Fri Sat'
+++++++++++++AXTable AXRoleDescription='table' AXDescription='S M T W T F S Today'
 ++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Sun'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='S'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Mon'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='M'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Tue'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='T'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Wed'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='W'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Thu'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='T'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Fri'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='F'
 ++++++++++++++++AXGroup AXRoleDescription='group'
-++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='Sat'
+++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='S'
 ++++++++++++++AXGroup AXRoleDescription='group'
 ++++++++++++++++AXGroup AXRoleDescription='group'
+++++++++++++++AXButton AXRoleDescription='button' AXDescription='Today'
 ++++++++++++++AXGroup AXRoleDescription='group'
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-blink.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-blink.txt
new file mode 100644
index 0000000..7cf6adf
--- /dev/null
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-blink.txt
@@ -0,0 +1,87 @@
+rootWebArea
+++genericContainer
+++++date inputType='date' value='2008-09-01'
+++++++genericContainer
+++++++++genericContainer
+++++++++++spinButton name='Month' value='09' valueForRange=9.00 minValueForRange=1.00 maxValueForRange=12.00
+++++++++++++staticText name='09'
+++++++++++++++inlineTextBox name='09'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Day' value='01' valueForRange=1.00 minValueForRange=1.00 maxValueForRange=31.00
+++++++++++++staticText name='01'
+++++++++++++++inlineTextBox name='01'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Year' value='2008' valueForRange=2008.00 minValueForRange=1.00 maxValueForRange=275760.00
+++++++++++++staticText name='2008'
+++++++++++++++inlineTextBox name='2008'
+++++++popUpButton name='Show date picker'
+++++date inputType='date' value='2008-09-01'
+++++++genericContainer
+++++++++genericContainer
+++++++++++spinButton name='Month' value='09' valueForRange=9.00 minValueForRange=1.00 maxValueForRange=12.00
+++++++++++++staticText name='09'
+++++++++++++++inlineTextBox name='09'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Day' value='01' valueForRange=1.00 minValueForRange=1.00 maxValueForRange=31.00
+++++++++++++staticText name='01'
+++++++++++++++inlineTextBox name='01'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Year' value='2008' valueForRange=2008.00 minValueForRange=1.00 maxValueForRange=275760.00
+++++++++++++staticText name='2008'
+++++++++++++++inlineTextBox name='2008'
+++++++popUpButton name='Show date picker'
+++++date inputType='date' name='Third date picker' value='2008-09-01' controlsIds=rootWebArea
+++++++genericContainer
+++++++++genericContainer
+++++++++++spinButton name='Month Third date picker' value='09' valueForRange=9.00 minValueForRange=1.00 maxValueForRange=12.00
+++++++++++++staticText name='09'
+++++++++++++++inlineTextBox name='09'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Day Third date picker' value='01' valueForRange=1.00 minValueForRange=1.00 maxValueForRange=31.00
+++++++++++++staticText name='01'
+++++++++++++++inlineTextBox name='01'
+++++++++++staticText name='/'
+++++++++++++inlineTextBox name='/'
+++++++++++spinButton name='Year Third date picker' value='2008' valueForRange=2008.00 minValueForRange=1.00 maxValueForRange=275760.00
+++++++++++++staticText name='2008'
+++++++++++++++inlineTextBox name='2008'
+++++++popUpButton name='Show date picker'
+++++++rootWebArea
+++++++++genericContainer ignored
+++++++++++genericContainer
+++++++++++++genericContainer
+++++++++++++++genericContainer ignored
+++++++++++++++++genericContainer
+++++++++++++++++++button name='Show month selection panel'
+++++++++++++++++++++staticText
+++++++++++++++++++++svgRoot
+++++++++++++++++button name='Show previous month'
+++++++++++++++++++svgRoot
+++++++++++++++++button name='Show next month'
+++++++++++++++++++svgRoot
+++++++++++++++grid
+++++++++++++++++genericContainer
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Su'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Mo'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Tu'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='We'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Th'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Fr'
+++++++++++++++++++genericContainer
+++++++++++++++++++++staticText name='Sa'
+++++++++++++++++genericContainer
+++++++++++++++++++genericContainer
+++++++++++++++++button name='Today'
+++++++++++++++++++staticText name='Today'
+
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-uia-win.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt
similarity index 100%
rename from content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-uia-win.txt
rename to content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-win.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-win.txt
similarity index 100%
rename from content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-win.txt
rename to content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-win.txt
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win.html b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win.html
new file mode 100644
index 0000000..4cdd93b9
--- /dev/null
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win.html
@@ -0,0 +1,24 @@
+<!--
+@BLINK-ALLOW:inputType=*
+@MAC-ALLOW:AXRole*
+@UIA-WIN-ALLOW:ControllerFor=*
+@UIA-WIN-ALLOW:LocalizedControlType='date picker'
+@DEFAULT-ACTION-ON:Show date picker,Third date picker
+@WAIT-FOR:Today
+
+Windows 7 formats dates differently than Windows 10 (September, 2008 in Windows
+7 vs September 2008 in Windows 10), so skip the name attribute in this case
+so this test can pass on both platforms.
+
+@BLINK-DENY:name='September*
+@WIN-DENY:name='September*
+@UIA-WIN-DENY:Name='September*
+-->
+<!DOCTYPE html>
+<html>
+<body>
+  <input type="date" value="2008-09-01">
+  <input type="date" value="2008-09-01">
+  <input type="date" value="2008-09-01" aria-label="Third date picker">
+</body>
+</html>
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index c350189..cfc5f2a 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -43,11 +43,6 @@
 crbug.com/609629 [ android qualcomm-adreno-(tm)-420 ] ContextLost_WebGLContextLostFromGPUProcessExit [ Skip ]
 crbug.com/609629 [ android qualcomm-adreno-(tm)-420 ] ContextLost_WebGLContextLostInHiddenTab [ Skip ]
 
-# RetryOnFailure flaky mac test until root cause can be investigated.
-crbug.com/965268 [ mac ] ContextLost_WebGLUnblockedAfterUserInitiatedReload [ RetryOnFailure ]
-crbug.com/1031095 [ mac ] GpuCrash_GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash [ RetryOnFailure ]
-crbug.com/1031567 [ mac ] ContextLost_WebGLContextLostFromGPUProcessExit [ RetryOnFailure ]
-
 # Mac NVIDIA only uses the low-power GPU.
 crbug.com/681341 [ mac nvidia ] ContextLost_MacWebGLMultisamplingHighPowerSwitchLosesContext [ Skip ]
 crbug.com/681341 [ mac nvidia ] ContextLost_MacWebGLPreserveDBHighPowerSwitchLosesContext [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index 1291d3d..a92d5ff6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -71,6 +71,10 @@
 # Produces black images on Nexus 5Xs in Android Webview (qualcomm-adreno-(tm)-418) crbug.com/984352
 # Fails on Pixel 2 (qualcomm-adreno-(tm)-540) crbug.com/966069
 crbug.com/805739 [ android ] Pixel_CanvasLowLatency2D [ Skip ]
+crbug.com/1039232 [ android android-chromium qualcomm-adreno-(tm)-540 use-vulkan skia-renderer ] Pixel_CanvasLowLatencyWebGL [ Failure ]
+crbug.com/1039232 [ android android-chromium qualcomm-adreno-(tm)-540 use-vulkan skia-renderer ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Failure ]
+crbug.com/1039232 [ android android-chromium qualcomm-adreno-(tm)-540 use-vulkan skia-renderer ] Pixel_OffscreenCanvasWebGLDefaultWorker [ Failure ]
+crbug.com/1039232 [ android android-chromium qualcomm-adreno-(tm)-540 use-vulkan skia-renderer ] Pixel_RepeatedWebGLTo2D [ Failure ]
 
 # Skip test that kills GPU process since Android Webview only supports
 # in-process GPU.
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 4171554..6541f996 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
@@ -727,6 +727,7 @@
 crbug.com/906737 [ android qualcomm ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
 crbug.com/906742 [ android qualcomm no-passthrough ] conformance2/glsl3/compare-structs-containing-arrays.html [ Failure ]
 crbug.com/1008535 [ android qualcomm-adreno-(tm)-540 passthrough ] conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html [ Skip ]
+crbug.com/1000354 [ android qualcomm-adreno-(tm)-540 passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ]
 crbug.com/981216 [ android qualcomm-adreno-(tm)-540 ] deqp/functional/gles3/fbocolorbuffer/tex2d_01.html [ RetryOnFailure ]
 crbug.com/949321 [ android qualcomm ] deqp/functional/gles3/framebufferblit/default_framebuffer_02.html [ RetryOnFailure ]
 crbug.com/1022410 [ android qualcomm ] conformance2/transform_feedback/switching-objects.html [ RetryOnFailure ]
diff --git a/content/test/test_navigation_url_loader_factory.cc b/content/test/test_navigation_url_loader_factory.cc
index b9ee24f..e12ce13 100644
--- a/content/test/test_navigation_url_loader_factory.cc
+++ b/content/test/test_navigation_url_loader_factory.cc
@@ -25,7 +25,7 @@
     StoragePartition* storage_partition,
     std::unique_ptr<NavigationRequestInfo> request_info,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
-    ServiceWorkerNavigationHandle* service_worker_handle,
+    ServiceWorkerMainResourceHandle* service_worker_handle,
     NavigationURLLoaderDelegate* delegate,
     bool is_served_from_back_forward_cache) {
   return std::unique_ptr<NavigationURLLoader>(new TestNavigationURLLoader(
diff --git a/content/test/test_navigation_url_loader_factory.h b/content/test/test_navigation_url_loader_factory.h
index bfa9a08e..9c4e17e7 100644
--- a/content/test/test_navigation_url_loader_factory.h
+++ b/content/test/test_navigation_url_loader_factory.h
@@ -27,7 +27,7 @@
       StoragePartition* storage_partition,
       std::unique_ptr<NavigationRequestInfo> request_info,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
-      ServiceWorkerNavigationHandle* service_worker_handle,
+      ServiceWorkerMainResourceHandle* service_worker_handle,
       NavigationURLLoaderDelegate* delegate,
       bool is_served_from_back_forward_cache) override;
 
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index f3692d8..04e5209 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -259,6 +259,7 @@
     mojom::CommonNavigationParamsPtr common_params,
     mojom::CommitNavigationParamsPtr commit_params,
     int error_code,
+    const net::ResolveErrorInfo& resolve_error_info,
     const base::Optional<std::string>& error_page_content) {
   mock_navigation_client_.reset();
   BindNavigationClient(
@@ -266,8 +267,8 @@
           .BindNewEndpointAndPassDedicatedReceiverForTesting());
   mock_navigation_client_->CommitFailedNavigation(
       std::move(common_params), std::move(commit_params),
-      false /* has_stale_copy_in_cache */, error_code, error_page_content,
-      nullptr,
+      false /* has_stale_copy_in_cache */, error_code, resolve_error_info,
+      error_page_content, nullptr,
       base::BindOnce(&MockFrameHost::DidCommitProvisionalLoad,
                      base::Unretained(mock_frame_host_.get())));
 }
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index c051e903..8dc9c3f 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -50,6 +50,7 @@
   void NavigateWithError(mojom::CommonNavigationParamsPtr common_params,
                          mojom::CommitNavigationParamsPtr request_params,
                          int error_code,
+                         const net::ResolveErrorInfo& resolve_error_info,
                          const base::Optional<std::string>& error_page_content);
   void SwapOut(int proxy_routing_id,
                bool is_loading,
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index e6e6d852..a4714db 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -169,11 +169,6 @@
   return gfx::Rect();
 }
 
-void TestRenderWidgetHostView::DidCreateNewRendererCompositorFrameSink(
-    viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
-  did_change_compositor_frame_sink_ = true;
-}
-
 void TestRenderWidgetHostView::SubmitCompositorFrame(
     const viz::LocalSurfaceId& local_surface_id,
     viz::CompositorFrame frame,
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index f948c7b7..50a242d 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -86,9 +86,6 @@
   void ShowDefinitionForSelection() override {}
   void SpeakSelection() override;
 #endif  // defined(OS_MACOSX)
-  void DidCreateNewRendererCompositorFrameSink(
-      viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
-      override;
   void SubmitCompositorFrame(
       const viz::LocalSurfaceId& local_surface_id,
       viz::CompositorFrame frame,
@@ -128,12 +125,7 @@
   bool is_occluded() const { return is_occluded_; }
   bool did_swap_compositor_frame() const { return did_swap_compositor_frame_; }
   void reset_did_swap_compositor_frame() { did_swap_compositor_frame_ = false; }
-  bool did_change_compositor_frame_sink() {
-    return did_change_compositor_frame_sink_;
-  }
-  void reset_did_change_compositor_frame_sink() {
-    did_change_compositor_frame_sink_ = false;
-  }
+
   // viz::HostFrameSinkClient implementation.
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
@@ -148,7 +140,6 @@
   bool is_showing_;
   bool is_occluded_;
   bool did_swap_compositor_frame_;
-  bool did_change_compositor_frame_sink_ = false;
   ui::DummyTextInputClient text_input_client_;
 
 #if defined(USE_AURA)
diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn
index 63a00fa..fec22382 100644
--- a/courgette/BUILD.gn
+++ b/courgette/BUILD.gn
@@ -22,8 +22,6 @@
     "disassembler.h",
     "disassembler_elf_32.cc",
     "disassembler_elf_32.h",
-    "disassembler_elf_32_arm.cc",
-    "disassembler_elf_32_arm.h",
     "disassembler_elf_32_x86.cc",
     "disassembler_elf_32_x86.h",
     "disassembler_win32.cc",
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc
index 58c16b4..fd73612 100644
--- a/courgette/assembly_program.cc
+++ b/courgette/assembly_program.cc
@@ -31,7 +31,6 @@
   // InstructionReceptor:
   CheckBool EmitPeRelocs() override { return true; }
   CheckBool EmitElfRelocation() override { return true; }
-  CheckBool EmitElfARMRelocation() override { return true; }
   CheckBool EmitOrigin(RVA rva) override { return true; }
   CheckBool EmitSingleByte(uint8_t byte) override { return true; }
   CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
@@ -41,13 +40,6 @@
     rel32_vector_.push_back(label);
     return true;
   }
-  CheckBool EmitRel32ARM(uint16_t op,
-                         Label* label,
-                         const uint8_t* arm_op,
-                         uint16_t op_size) override {
-    rel32_vector_.push_back(label);
-    return true;
-  }
   CheckBool EmitAbs32(Label* label) override {
     abs32_vector_.push_back(label);
     return true;
@@ -75,7 +67,8 @@
                                        RvaVisitor* rel32_visitor) {
   abs32_label_manager_.Read(abs32_visitor);
   rel32_label_manager_.Read(rel32_visitor);
-  TrimLabels();
+  // TrimLabels() should be called here if used. Previously this was used only
+  // for ARM binaries, but ARM support has been deprecated.
 }
 
 // Chosen empirically to give the best reduction in payload size for
@@ -83,10 +76,6 @@
 const int AssemblyProgram::kLabelLowerLimit = 5;
 
 void AssemblyProgram::TrimLabels() {
-  // For now only trim for ARM binaries.
-  if (kind() != EXE_ELF_32_ARM)
-    return;
-
   int lower_limit = kLabelLowerLimit;
 
   VLOG(1) << "TrimLabels: threshold " << lower_limit;
diff --git a/courgette/courgette.h b/courgette/courgette.h
index 5337566..a95fbd59 100644
--- a/courgette/courgette.h
+++ b/courgette/courgette.h
@@ -57,7 +57,7 @@
   EXE_UNKNOWN = 0,
   EXE_WIN_32_X86 = 1,
   EXE_ELF_32_X86 = 2,
-  EXE_ELF_32_ARM = 3,
+  // EXE_ELF_32_ARM_DEPRECATED = 3,  // DEPRECATED.
   EXE_WIN_32_X64 = 4,
 };
 
diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc
index 383a92dc..9d904a5 100644
--- a/courgette/courgette_tool.cc
+++ b/courgette/courgette_tool.cc
@@ -135,11 +135,6 @@
       result = true;
       break;
 
-    case courgette::EXE_ELF_32_ARM:
-      format = "ELF 32 ARM";
-      result = true;
-      break;
-
     case courgette::EXE_WIN_32_X64:
       format = "Windows 64 PE";
       result = true;
diff --git a/courgette/description.html b/courgette/description.html
index 8fe4538b..e4854d3 100644
--- a/courgette/description.html
+++ b/courgette/description.html
@@ -41,7 +41,6 @@
 <ul>
 <li><p>disassembler_win32_x86.h defines the PE/COFF x86 disassembler</p></li>
 <li><p>disassembler_elf_32_x86.h defines the ELF 32-bit x86 disassembler</p></li>
-<li><p>disassembler_elf_32_arm.h defines the ELF 32-bit arm disassembler</p></li>
 </ul></li>
 <li><p>The Disassembler replaces the relocation table with a Courgette
 instruction that can regenerate the relocation table.</p></li>
diff --git a/courgette/description.md b/courgette/description.md
index f79f99e6..533d4c3 100644
--- a/courgette/description.md
+++ b/courgette/description.md
@@ -46,8 +46,6 @@
 
   - disassembler\_elf\_32\_x86.h defines the ELF 32-bit x86 disassembler
 
-  - disassembler\_elf\_32\_arm.h defines the ELF 32-bit arm disassembler
-
 - The Disassembler replaces the relocation table with a Courgette
   instruction that can regenerate the relocation table.
 
diff --git a/courgette/disassembler_elf_32_arm.cc b/courgette/disassembler_elf_32_arm.cc
deleted file mode 100644
index b4fbf3f0..0000000
--- a/courgette/disassembler_elf_32_arm.cc
+++ /dev/null
@@ -1,538 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "courgette/disassembler_elf_32_arm.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "courgette/assembly_program.h"
-#include "courgette/courgette.h"
-
-namespace courgette {
-
-CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type,
-                                         uint32_t arm_op,
-                                         RVA rva,
-                                         uint16_t* c_op,
-                                         uint32_t* addr) {
-  // Notation for bit ranges in comments:
-  // - Listing bits from highest to lowest.
-  // - A-Z or (j1), (j2), etc.: single bit in source.
-  // - a-z: multiple, consecutive bits in source.
-  switch (type) {
-    case ARM_OFF8: {
-      // Encoding T1.
-      // The offset is given by lower 8 bits of the op.  It is a 9-bit offset,
-      // shifted right 1 bit, and signed extended.
-      // arm_op = aaaaaaaa Snnnnnnn
-      // *addr := SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100
-      // *c_op := 00010000 aaaaaaaa
-      uint32_t temp = (arm_op & 0x00FF) << 1;
-      if (temp & 0x0100)
-        temp |= 0xFFFFFE00;
-      temp += 4;  // Offset from _next_ PC.
-
-      (*addr) = temp;
-      (*c_op) = static_cast<uint16_t>(arm_op >> 8) | 0x1000;
-      break;
-    }
-    case ARM_OFF11: {
-      // Encoding T2.
-      // The offset is given by lower 11 bits of the op, and is a 12-bit offset,
-      // shifted right 1 bit, and sign extended.
-      // arm_op = aaaaaSnn nnnnnnnn
-      // *addr := SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100
-      // *c_op := 00100000 000aaaaa
-      uint32_t temp = (arm_op & 0x07FF) << 1;
-      if (temp & 0x00000800)
-        temp |= 0xFFFFF000;
-      temp += 4;  // Offset from _next_ PC.
-
-      (*addr) = temp;
-      (*c_op) = static_cast<uint16_t>(arm_op >> 11) | 0x2000;
-      break;
-    }
-    case ARM_OFF24: {
-      // The offset is given by the lower 24-bits of the op, shifted
-      // left 2 bits, and sign extended.
-      // arm_op = aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn
-      // *addr := SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000
-      // *c_op := 00110000 aaaaaaaa
-      uint32_t temp = (arm_op & 0x00FFFFFF) << 2;
-      if (temp & 0x02000000)
-        temp |= 0xFC000000;
-      temp += 8;
-
-      (*addr) = temp;
-      (*c_op) = (arm_op >> 24) | 0x3000;
-      break;
-    }
-    case ARM_OFF25: {
-      // Encoding T4.
-      // arm_op = aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn
-      //   where CD is in {01, 10, 11}
-      // i1 := ~(j1 ^ S)
-      // i2 := ~(j2 ^ S)
-      // If CD == 10:
-      //   pppp := (rva % 4 == 0) ? 0100 : 0010
-      // Else:
-      //   pppp := 0100
-      // *addr := SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp
-      // *c_op := 0100pppp aaaaaBCD
-      // TODO(huangs): aaaaa = 11110 and B = 1 always? Investigate and fix.
-      uint32_t temp = 0;
-      temp |= (arm_op & 0x000007FF) << 1;  // imm11
-      temp |= (arm_op & 0x03FF0000) >> 4;  // imm10
-
-      uint32_t S = (arm_op & (1 << 26)) >> 26;
-      uint32_t j2 = (arm_op & (1 << 11)) >> 11;
-      uint32_t j1 = (arm_op & (1 << 13)) >> 13;
-      bool bit12 = ((arm_op & (1 << 12)) >> 12) != 0;  // D
-      bool bit14 = ((arm_op & (1 << 14)) >> 14) != 0;  // C
-
-      uint32_t i2 = ~(j2 ^ S) & 1;
-      uint32_t i1 = ~(j1 ^ S) & 1;
-      bool toARM =  bit14 && !bit12;
-
-      temp |= (S << 24) | (i1 << 23) | (i2 << 22);
-
-      if (temp & 0x01000000)  // sign extension
-        temp |= 0xFE000000;
-      uint32_t prefetch;
-      if (toARM) {
-        // Align PC on 4-byte boundary.
-        uint32_t align4byte = (rva % 4) ? 2 : 4;
-        prefetch = align4byte;
-      } else {
-        prefetch = 4;
-      }
-      temp += prefetch;
-      (*addr) = temp;
-
-      uint32_t temp2 = 0x4000;
-      temp2 |= (arm_op & (1 << 12)) >> 12;   // .......D
-      temp2 |= (arm_op & (1 << 14)) >> 13;   // ......C.
-      temp2 |= (arm_op & (1 << 15)) >> 13;   // .....B..
-      temp2 |= (arm_op & 0xF8000000) >> 24;  // aaaaa...
-      temp2 |= (prefetch & 0x0000000F) << 8;
-      (*c_op) = static_cast<uint16_t>(temp2);
-      break;
-    }
-    case ARM_OFF21: {
-      // Encoding T3.
-      // arm_op = 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn
-      // *addr := SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100
-      // *c_op := 01010000 0000cccc
-      uint32_t temp = 0;
-      temp |= (arm_op & 0x000007FF) << 1;  // imm11
-      temp |= (arm_op & 0x003F0000) >> 4;  // imm6
-
-      uint32_t S = (arm_op & (1 << 26)) >> 26;
-      // TODO(huangs): Check with docs: Perhaps j1, j2 should swap?
-      uint32_t j2 = (arm_op & (1 << 11)) >> 11;
-      uint32_t j1 = (arm_op & (1 << 13)) >> 13;
-
-      temp |= (S << 20) | (j1 << 19) | (j2 << 18);
-
-      if (temp & 0x00100000)  // sign extension
-        temp |= 0xFFE00000;
-      temp += 4;
-      (*addr) = temp;
-
-      uint32_t temp2 = 0x5000;
-      temp2 |= (arm_op & 0x03C00000) >> 22;  // just save the cond
-      (*c_op) = static_cast<uint16_t>(temp2);
-      break;
-    }
-    default:
-      return false;
-  }
-  return true;
-}
-
-CheckBool DisassemblerElf32ARM::Decompress(ARM_RVA type,
-                                           uint16_t c_op,
-                                           uint32_t addr,
-                                           uint32_t* arm_op) {
-  switch (type) {
-    case ARM_OFF8:
-      // addr     = SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100
-      // c_op     = 00010000 aaaaaaaa
-      // *arm_op := aaaaaaaa Snnnnnnn
-      (*arm_op) = ((c_op & 0x0FFF) << 8) | (((addr - 4) >> 1) & 0x000000FF);
-      break;
-    case ARM_OFF11:
-      // addr     = SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100
-      // c_op     = 00100000 000aaaaa
-      // *arm_op := aaaaaSnn nnnnnnnn
-      (*arm_op) = ((c_op & 0x0FFF) << 11) | (((addr - 4) >> 1) & 0x000007FF);
-      break;
-    case ARM_OFF24:
-      // addr     = SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000
-      // c_op     = 00110000 aaaaaaaa
-      // *arm_op := aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn
-      (*arm_op) = ((c_op & 0x0FFF) << 24) | (((addr - 8) >> 2) & 0x00FFFFFF);
-      break;
-    case ARM_OFF25: {
-      // addr     = SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp
-      // c_op     = 0100pppp aaaaaBCD
-      // j1      := ~i1 ^ S
-      // j2      := ~i2 ^ S
-      // *arm_op := aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn
-      uint32_t temp = 0;
-      temp |= (c_op & (1 << 0)) << 12;
-      temp |= (c_op & (1 << 1)) << 13;
-      temp |= (c_op & (1 << 2)) << 13;
-      temp |= (c_op & (0xF8000000 >> 24)) << 24;
-
-      uint32_t prefetch = (c_op & 0x0F00) >> 8;
-      addr -= prefetch;
-
-      addr &= 0x01FFFFFF;
-
-      uint32_t S = (addr & (1 << 24)) >> 24;
-      uint32_t i1 = (addr & (1 << 23)) >> 23;
-      uint32_t i2 = (addr & (1 << 22)) >> 22;
-
-      uint32_t j1 = ((~i1) ^ S) & 1;
-      uint32_t j2 = ((~i2) ^ S) & 1;
-
-      temp |= S << 26;
-      temp |= j2 << 11;
-      temp |= j1 << 13;
-
-      temp |= (addr & (0x000007FF << 1)) >> 1;
-      temp |= (addr & (0x03FF0000 >> 4)) << 4;
-
-      (*arm_op) = temp;
-      break;
-    }
-    case ARM_OFF21: {
-      // addr     = SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100
-      // c_op     = 01010000 0000cccc
-      // *arm_op := 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn
-      uint32_t temp = 0xF0008000;
-      temp |= (c_op & (0x03C00000 >> 22)) << 22;
-
-      addr -= 4;
-      addr &= 0x001FFFFF;
-
-      uint32_t S = (addr & (1 << 20)) >> 20;
-      uint32_t j1 = (addr & (1 << 19)) >> 19;
-      uint32_t j2 = (addr & (1 << 18)) >> 18;
-
-      temp |= S << 26;
-      temp |= j2 << 11;
-      temp |= j1 << 13;
-
-      temp |= (addr & (0x000007FF << 1)) >> 1;
-      temp |= (addr & (0x003F0000 >> 4)) << 4;
-
-      (*arm_op) = temp;
-      break;
-    }
-    default:
-      return false;
-  }
-  return true;
-}
-
-uint16_t DisassemblerElf32ARM::TypedRVAARM::op_size() const {
-  switch (type_) {
-    case ARM_OFF8:
-      return 2;
-    case ARM_OFF11:
-      return 2;
-    case ARM_OFF24:
-      return 4;
-    case ARM_OFF25:
-      return 4;
-    case ARM_OFF21:
-      return 4;
-    default:
-      return 0xFFFF;
-  }
-}
-
-CheckBool DisassemblerElf32ARM::TypedRVAARM::ComputeRelativeTarget(
-    const uint8_t* op_pointer) {
-  arm_op_ = op_pointer;
-  switch (type_) {
-    case ARM_OFF8:  // Falls through.
-    case ARM_OFF11: {
-      RVA relative_target;
-      CheckBool ret = Compress(type_,
-                               Read16LittleEndian(op_pointer),
-                               rva(),
-                               &c_op_,
-                               &relative_target);
-      set_relative_target(relative_target);
-      return ret;
-    }
-    case ARM_OFF24: {
-      RVA relative_target;
-      CheckBool ret = Compress(type_,
-                               Read32LittleEndian(op_pointer),
-                               rva(),
-                               &c_op_,
-                               &relative_target);
-      set_relative_target(relative_target);
-      return ret;
-    }
-    case ARM_OFF25:  // Falls through.
-    case ARM_OFF21: {
-      // A thumb-2 op is 32 bits stored as two 16-bit words
-      uint32_t pval = (Read16LittleEndian(op_pointer) << 16) |
-                      Read16LittleEndian(op_pointer + 2);
-      RVA relative_target;
-      CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target);
-      set_relative_target(relative_target);
-      return ret;
-    }
-   default:
-     return false;
-  }
-}
-
-CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction(
-    Label* label,
-    InstructionReceptor* receptor) {
-  return receptor->EmitRel32ARM(c_op(), label, arm_op_, op_size());
-}
-
-DisassemblerElf32ARM::DisassemblerElf32ARM(const uint8_t* start, size_t length)
-    : DisassemblerElf32(start, length) {}
-
-// Convert an ELF relocation struction into an RVA.
-CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const {
-  // The rightmost byte of r_info is the type.
-  elf32_rel_arm_type_values type =
-      static_cast<elf32_rel_arm_type_values>(rel.r_info & 0xFF);
-
-  // The other 3 bytes of r_info are the symbol.
-  uint32_t symbol = rel.r_info >> 8;
-
-  switch (type) {
-    case R_ARM_RELATIVE:
-      if (symbol != 0)
-        return false;
-
-      // This is a basic ABS32 relocation address.
-      *result = rel.r_offset;
-      return true;
-
-    default:
-      return false;
-  }
-}
-
-CheckBool DisassemblerElf32ARM::ParseRelocationSection(
-    const Elf32_Shdr* section_header,
-    InstructionReceptor* receptor) const {
-  // This method compresses a contiguous stretch of R_ARM_RELATIVE entries in
-  // the relocation table with a Courgette relocation table instruction.
-  // It skips any entries at the beginning that appear in a section that
-  // Courgette doesn't support, e.g. INIT.
-  //
-  // Specifically, the entries should be
-  //   (1) In the same relocation table
-  //   (2) Are consecutive
-  //   (3) Are sorted in memory address order
-  //
-  // Happily, this is normally the case, but it's not required by spec so we
-  // check, and just don't do it if we don't match up.
-  //
-  // The expectation is that one relocation section will contain all of our
-  // R_ARM_RELATIVE entries in the expected order followed by assorted other
-  // entries we can't use special handling for.
-
-  bool match = true;
-
-  // Walk all the bytes in the section, matching relocation table or not.
-  FileOffset file_offset = section_header->sh_offset;
-  FileOffset section_end = section_header->sh_offset + section_header->sh_size;
-
-  const Elf32_Rel* section_relocs_iter = reinterpret_cast<const Elf32_Rel*>(
-      FileOffsetToPointer(section_header->sh_offset));
-
-  uint32_t section_relocs_count =
-      section_header->sh_size / section_header->sh_entsize;
-
-  if (abs32_locations_.size() > section_relocs_count)
-    match = false;
-
-  if (match && !abs32_locations_.empty()) {
-    std::vector<RVA>::const_iterator reloc_iter = abs32_locations_.begin();
-
-    // Look for the first reloc unit matching |abs32_locations_[0]|.
-    size_t section_relocs_remaining = section_relocs_count;
-    for (; section_relocs_remaining > 0; --section_relocs_remaining) {
-      if (section_relocs_iter->r_info == R_ARM_RELATIVE &&
-          section_relocs_iter->r_offset == *reloc_iter) {
-        break;
-      }
-
-      if (!ParseSimpleRegion(file_offset, file_offset + sizeof(Elf32_Rel),
-                             receptor)) {
-        return false;
-      }
-
-      file_offset += sizeof(Elf32_Rel);
-      ++section_relocs_iter;
-    }
-
-    // If there aren't enough reloc units left then don't bother matching. This
-    // can happen if the reloc units are not sorted.
-    if (abs32_locations_.size() > section_relocs_remaining)
-      match = false;
-
-    // Try to match successive reloc units with (sorted) |abs32_locations_|.
-    while (match && (reloc_iter != abs32_locations_.end())) {
-      if (section_relocs_iter->r_info != R_ARM_RELATIVE ||
-          section_relocs_iter->r_offset != *reloc_iter) {
-        match = false;
-      }
-
-      ++section_relocs_iter;
-      ++reloc_iter;
-      file_offset += sizeof(Elf32_Rel);
-    }
-
-    if (match) {
-      // Success: Emit relocation table.
-      if (!receptor->EmitElfARMRelocation())
-        return false;
-    }
-  }
-
-  return ParseSimpleRegion(file_offset, section_end, receptor);
-}
-
-// TODO(huangs): Detect and avoid overlap with abs32 addresses.
-CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection(
-    const Elf32_Shdr* section_header) {
-  FileOffset start_file_offset = section_header->sh_offset;
-  FileOffset end_file_offset = start_file_offset + section_header->sh_size;
-
-  const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
-  const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
-
-  // Quick way to convert from Pointer to RVA within a single Section is to
-  // subtract |pointer_to_rva|.
-  const uint8_t* const adjust_pointer_to_rva =
-      start_pointer - section_header->sh_addr;
-
-  // Find the rel32 relocations.
-  const uint8_t* p = start_pointer;
-  bool on_32bit = 1;  // 32-bit ARM ops appear on 32-bit boundaries, so track it
-  while (p < end_pointer) {
-    // Heuristic discovery of rel32 locations in instruction stream: are the
-    // next few bytes the start of an instruction containing a rel32
-    // addressing mode?
-    std::unique_ptr<TypedRVAARM> rel32_rva;
-    RVA target_rva = 0;
-    bool found = false;
-
-    // 16-bit thumb ops
-    if (!found && p + 3 <= end_pointer) {
-      uint16_t pval = Read16LittleEndian(p);
-      if ((pval & 0xF000) == 0xD000) {
-        RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
-        rel32_rva.reset(new TypedRVAARM(ARM_OFF8, rva));
-        if (!rel32_rva->ComputeRelativeTarget(p))
-          return false;
-
-        target_rva = rel32_rva->rva() + rel32_rva->relative_target();
-        found = true;
-      } else if ((pval & 0xF800) == 0xE000) {
-        RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
-        rel32_rva.reset(new TypedRVAARM(ARM_OFF11, rva));
-        if (!rel32_rva->ComputeRelativeTarget(p))
-          return false;
-
-        target_rva = rel32_rva->rva() + rel32_rva->relative_target();
-        found = true;
-      }
-    }
-
-    // thumb-2 ops comprised of two 16-bit words.
-    if (!found && p + 5 <= end_pointer) {
-      // This is really two 16-bit words, not one 32-bit word.
-      uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2);
-      if ((pval & 0xF8008000) == 0xF0008000) {
-        // Covers thumb-2's 32-bit conditional/unconditional branches
-        if ((pval & (1 << 14)) || (pval & (1 << 12))) {
-          // A branch, with link, or with link and exchange.
-          RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
-          rel32_rva.reset(new TypedRVAARM(ARM_OFF25, rva));
-          if (!rel32_rva->ComputeRelativeTarget(p))
-            return false;
-
-          target_rva = rel32_rva->rva() + rel32_rva->relative_target();
-          found = true;
-
-        } else {
-          // TODO(paulgazz) make sure cond is not 111
-          // A conditional branch instruction
-          RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
-          rel32_rva.reset(new TypedRVAARM(ARM_OFF21, rva));
-          if (!rel32_rva->ComputeRelativeTarget(p))
-            return false;
-
-          target_rva = rel32_rva->rva() + rel32_rva->relative_target();
-          found = true;
-        }
-      }
-    }
-
-    // 32-bit ARM ops.
-    if (!found && on_32bit && (p + 5) <= end_pointer) {
-      uint32_t pval = Read32LittleEndian(p);
-      if ((pval & 0x0E000000) == 0x0A000000) {
-        // Covers both 0x0A 0x0B ARM relative branches
-        RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
-        rel32_rva.reset(new TypedRVAARM(ARM_OFF24, rva));
-        if (!rel32_rva->ComputeRelativeTarget(p))
-          return false;
-
-        target_rva = rel32_rva->rva() + rel32_rva->relative_target();
-        found = true;
-      }
-    }
-
-    if (found && IsValidTargetRVA(target_rva)) {
-      uint16_t op_size = rel32_rva->op_size();
-      rel32_locations_.push_back(std::move(rel32_rva));
-#if COURGETTE_HISTOGRAM_TARGETS
-      ++rel32_target_rvas_[target_rva];
-#endif
-      p += op_size;
-
-      // A tricky way to update the on_32bit flag. Here is the truth table:
-      // on_32bit | on_32bit   size is 4
-      // ---------+---------------------
-      // 1        | 0          0
-      // 0        | 0          1
-      // 0        | 1          0
-      // 1        | 1          1
-      on_32bit = (on_32bit == (op_size == 4));
-    } else {
-      // Move 2 bytes at a time, but track 32-bit boundaries
-      p += 2;
-      on_32bit = ((on_32bit + 1) % 2) != 0;
-    }
-  }
-
-  return true;
-}
-
-}  // namespace courgette
diff --git a/courgette/disassembler_elf_32_arm.h b/courgette/disassembler_elf_32_arm.h
deleted file mode 100644
index 120380616..0000000
--- a/courgette/disassembler_elf_32_arm.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COURGETTE_DISASSEMBLER_ELF_32_ARM_H_
-#define COURGETTE_DISASSEMBLER_ELF_32_ARM_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-
-#include "base/macros.h"
-#include "courgette/disassembler_elf_32.h"
-#include "courgette/types_elf.h"
-
-namespace courgette {
-
-class InstructionReceptor;
-
-enum ARM_RVA {
-  ARM_OFF8,
-  ARM_OFF11,
-  ARM_OFF24,
-  ARM_OFF25,
-  ARM_OFF21,
-};
-
-class DisassemblerElf32ARM : public DisassemblerElf32 {
- public:
-  // Returns true if a valid executable is detected using only quick checks.
-  static bool QuickDetect(const uint8_t* start, size_t length) {
-    return DisassemblerElf32::QuickDetect(start, length, EM_ARM);
-  }
-
-  class TypedRVAARM : public TypedRVA {
-   public:
-    TypedRVAARM(ARM_RVA type, RVA rva) : TypedRVA(rva), type_(type) { }
-    ~TypedRVAARM() override { }
-
-    // TypedRVA interfaces.
-    CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) override;
-    CheckBool EmitInstruction(Label* label,
-                              InstructionReceptor* receptor) override;
-    uint16_t op_size() const override;
-
-    uint16_t c_op() const { return c_op_; }
-
-   private:
-    ARM_RVA type_;
-    uint16_t c_op_;  // Set by ComputeRelativeTarget().
-    const uint8_t* arm_op_;
-  };
-
-  DisassemblerElf32ARM(const uint8_t* start, size_t length);
-
-  ~DisassemblerElf32ARM() override { }
-
-  // DisassemblerElf32 interfaces.
-  ExecutableType kind() const override { return EXE_ELF_32_ARM; }
-  e_machine_values ElfEM() const override { return EM_ARM; }
-
-  // Takes an ARM or thumb opcode |arm_op| of specified |type| and located at
-  // |rva|, extracts the instruction-relative target RVA into |*addr| and
-  // encodes the corresponding Courgette opcode as |*c_op|.
-  //
-  // Details on ARM opcodes, and target RVA extraction are taken from
-  // "ARM Architecture Reference Manual", section A4.1.5 and
-  // "Thumb-2 supplement", section 4.6.12.
-  // ARM_OFF24 is for the ARM opcode. The rest are for thumb opcodes.
-  static CheckBool Compress(ARM_RVA type,
-                            uint32_t arm_op,
-                            RVA rva,
-                            uint16_t* c_op /* out */,
-                            uint32_t* addr /* out */);
-
-  // Inverse for Compress(). Takes Courgette op |c_op| and relative address
-  // |addr| to reconstruct the original ARM or thumb op |*arm_op|.
-  static CheckBool Decompress(ARM_RVA type,
-                              uint16_t c_op,
-                              uint32_t addr,
-                              uint32_t* arm_op /* out */);
-
- protected:
-  // DisassemblerElf32 interfaces.
-  CheckBool RelToRVA(Elf32_Rel rel,
-                     RVA* result) const override WARN_UNUSED_RESULT;
-  CheckBool ParseRelocationSection(const Elf32_Shdr* section_header,
-                                   InstructionReceptor* receptor) const override
-      WARN_UNUSED_RESULT;
-  CheckBool ParseRel32RelocsFromSection(const Elf32_Shdr* section)
-      override WARN_UNUSED_RESULT;
-
-#if COURGETTE_HISTOGRAM_TARGETS
-  std::map<RVA, int> rel32_target_rvas_;
-#endif
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32ARM);
-};
-
-}  // namespace courgette
-
-#endif  // COURGETTE_DISASSEMBLER_ELF_32_ARM_H_
diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc
index a07baf3..2d0e40c 100644
--- a/courgette/encode_decode_unittest.cc
+++ b/courgette/encode_decode_unittest.cc
@@ -109,9 +109,4 @@
   TestAssembleToStreamDisassemble(file, 7308);
 }
 
-TEST_F(EncodeDecodeTest, Elf_Arm) {
-  std::string file = FileContents("elf-armv7");
-  TestAssembleToStreamDisassemble(file, 8531);
-}
-
 }  // namespace courgette
diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc
index c1f82bd..859f3d9 100644
--- a/courgette/encoded_program.cc
+++ b/courgette/encoded_program.cc
@@ -19,7 +19,6 @@
 #include "base/numerics/safe_math.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "courgette/disassembler_elf_32_arm.h"
 #include "courgette/label_manager.h"
 #include "courgette/streams.h"
 
@@ -144,9 +143,6 @@
   CheckBool EmitElfRelocation() override {
     return encoded_->AddElfMakeRelocs();
   }
-  CheckBool EmitElfARMRelocation() override {
-    return encoded_->AddElfARMMakeRelocs();
-  }
   CheckBool EmitOrigin(RVA rva) override { return encoded_->AddOrigin(rva); }
   CheckBool EmitSingleByte(uint8_t byte) override {
     return encoded_->AddCopy(1, &byte);
@@ -157,12 +153,6 @@
   CheckBool EmitRel32(Label* label) override {
     return encoded_->AddRel32(label->index_);
   }
-  CheckBool EmitRel32ARM(uint16_t op,
-                         Label* label,
-                         const uint8_t* arm_op,
-                         uint16_t op_size) override {
-    return encoded_->AddRel32ARM(op, label->index_);
-  }
   CheckBool EmitAbs32(Label* label) override {
     return encoded_->AddAbs32(label->index_);
   }
@@ -254,11 +244,6 @@
   return ops_.push_back(REL32) && rel32_ix_.push_back(label_index);
 }
 
-CheckBool EncodedProgram::AddRel32ARM(uint16_t op, int label_index) {
-  return ops_.push_back(static_cast<OP>(op)) &&
-      rel32_ix_.push_back(label_index);
-}
-
 CheckBool EncodedProgram::AddPeMakeRelocs(ExecutableType kind) {
   if (kind == EXE_WIN_32_X86)
     return ops_.push_back(MAKE_PE_RELOCATION_TABLE);
@@ -269,10 +254,6 @@
   return ops_.push_back(MAKE_ELF_RELOCATION_TABLE);
 }
 
-CheckBool EncodedProgram::AddElfARMMakeRelocs() {
-  return ops_.push_back(MAKE_ELF_ARM_RELOCATION_TABLE);
-}
-
 void EncodedProgram::DebuggingSummary() {
   VLOG(1) << "EncodedProgram Summary"
           << "\n  image base  " << image_base_
@@ -419,117 +400,6 @@
   return true;
 }
 
-CheckBool EncodedProgram::EvaluateRel32ARM(OP op,
-                                           size_t* ix_rel32_ix,
-                                           RVA* current_rva,
-                                           SinkStream* output) {
-  switch (op & 0x0000F000) {
-    case REL32ARM8: {
-      uint32_t index;
-      if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index))
-        return false;
-      ++(*ix_rel32_ix);
-      RVA rva;
-      if (!VectorAt(rel32_rva_, index, &rva))
-        return false;
-      uint32_t decompressed_op;
-      if (!DisassemblerElf32ARM::Decompress(
-              ARM_OFF8, static_cast<uint16_t>(op),
-              static_cast<uint32_t>(rva - *current_rva), &decompressed_op)) {
-        return false;
-      }
-      uint16_t op16 = static_cast<uint16_t>(decompressed_op);
-      if (!output->Write(&op16, 2))
-        return false;
-      *current_rva += 2;
-      break;
-    }
-    case REL32ARM11: {
-      uint32_t index;
-      if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index))
-        return false;
-      ++(*ix_rel32_ix);
-      RVA rva;
-      if (!VectorAt(rel32_rva_, index, &rva))
-        return false;
-      uint32_t decompressed_op;
-      if (!DisassemblerElf32ARM::Decompress(ARM_OFF11, (uint16_t)op,
-                                            (uint32_t)(rva - *current_rva),
-                                            &decompressed_op)) {
-        return false;
-      }
-      uint16_t op16 = static_cast<uint16_t>(decompressed_op);
-      if (!output->Write(&op16, 2))
-        return false;
-      *current_rva += 2;
-      break;
-    }
-    case REL32ARM24: {
-      uint32_t index;
-      if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index))
-        return false;
-      ++(*ix_rel32_ix);
-      RVA rva;
-      if (!VectorAt(rel32_rva_, index, &rva))
-        return false;
-      uint32_t decompressed_op;
-      if (!DisassemblerElf32ARM::Decompress(ARM_OFF24, (uint16_t)op,
-                                            (uint32_t)(rva - *current_rva),
-                                            &decompressed_op)) {
-        return false;
-      }
-      if (!output->Write(&decompressed_op, 4))
-        return false;
-      *current_rva += 4;
-      break;
-    }
-    case REL32ARM25: {
-      uint32_t index;
-      if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index))
-        return false;
-      ++(*ix_rel32_ix);
-      RVA rva;
-      if (!VectorAt(rel32_rva_, index, &rva))
-        return false;
-      uint32_t decompressed_op;
-      if (!DisassemblerElf32ARM::Decompress(ARM_OFF25, (uint16_t)op,
-                                            (uint32_t)(rva - *current_rva),
-                                            &decompressed_op)) {
-        return false;
-      }
-      uint32_t words = (decompressed_op << 16) | (decompressed_op >> 16);
-      if (!output->Write(&words, 4))
-        return false;
-      *current_rva += 4;
-      break;
-    }
-    case REL32ARM21: {
-      uint32_t index;
-      if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index))
-        return false;
-      ++(*ix_rel32_ix);
-      RVA rva;
-      if (!VectorAt(rel32_rva_, index, &rva))
-        return false;
-      uint32_t decompressed_op;
-      if (!DisassemblerElf32ARM::Decompress(ARM_OFF21, (uint16_t)op,
-                                            (uint32_t)(rva - *current_rva),
-                                            &decompressed_op)) {
-        return false;
-      }
-      uint32_t words = (decompressed_op << 16) | (decompressed_op >> 16);
-      if (!output->Write(&words, 4))
-        return false;
-      *current_rva += 4;
-      break;
-    }
-    default:
-      return false;
-  }
-
-  return true;
-}
-
 CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
   // For the most part, the assembly process walks the various tables.
   // ix_mumble is the index into the mumble table.
@@ -553,9 +423,7 @@
 
     switch (op) {
       default:
-        if (!EvaluateRel32ARM(op, &ix_rel32_ix, &current_rva, output))
-          return false;
-        break;
+        return false;
 
       case ORIGIN: {
         RVA section_rva;
@@ -670,18 +538,6 @@
         break;
       }
 
-      case MAKE_ELF_ARM_RELOCATION_TABLE: {
-        // We can see the base relocation anywhere, but we only have the
-        // information to generate it at the very end.  So we divert the bytes
-        // we are generating to a temporary stream.
-        if (pending_elf_relocation_table_type)
-          return false;  // Can't have two base relocation tables.
-
-        pending_elf_relocation_table_type = R_ARM_RELATIVE;
-        output = &bytes_following_relocation_table;
-        break;
-      }
-
       case MAKE_ELF_RELOCATION_TABLE: {
         // We can see the base relocation anywhere, but we only have the
         // information to generate it at the very end.  So we divert the bytes
diff --git a/courgette/encoded_program.h b/courgette/encoded_program.h
index 39051460..b814cbb 100644
--- a/courgette/encoded_program.h
+++ b/courgette/encoded_program.h
@@ -63,12 +63,10 @@
   CheckBool AddOrigin(RVA rva) WARN_UNUSED_RESULT;
   CheckBool AddCopy(size_t count, const void* bytes) WARN_UNUSED_RESULT;
   CheckBool AddRel32(int label_index) WARN_UNUSED_RESULT;
-  CheckBool AddRel32ARM(uint16_t op, int label_index) WARN_UNUSED_RESULT;
   CheckBool AddAbs32(int label_index) WARN_UNUSED_RESULT;
   CheckBool AddAbs64(int label_index) WARN_UNUSED_RESULT;
   CheckBool AddPeMakeRelocs(ExecutableType kind) WARN_UNUSED_RESULT;
   CheckBool AddElfMakeRelocs() WARN_UNUSED_RESULT;
-  CheckBool AddElfARMMakeRelocs() WARN_UNUSED_RESULT;
 
   // (3) Serialize binary assembly language tables to a set of streams.
   CheckBool WriteTo(SinkStreamSet* streams) WARN_UNUSED_RESULT;
@@ -94,23 +92,16 @@
     COPY = 1,    // COPY <count> <bytes> - copy bytes to output.
     COPY1 = 2,   // COPY1 <byte> - same as COPY 1 <byte>.
     REL32 = 3,   // REL32 <index> - emit rel32 encoded reference to address at
-                 // address table offset <index>
+                 // address table offset <index>.
     ABS32 = 4,   // ABS32 <index> - emit abs32 encoded reference to address at
-                 // address table offset <index>
-    MAKE_PE_RELOCATION_TABLE = 5,       // Emit PE base relocation table blocks.
-    MAKE_ELF_RELOCATION_TABLE = 6,      // Emit Elf relocation table for X86
-    MAKE_ELF_ARM_RELOCATION_TABLE = 7,  // Emit Elf relocation table for ARM
+                 // address table offset <index>.
+    MAKE_PE_RELOCATION_TABLE = 5,   // Emit PE base relocation table blocks.
+    MAKE_ELF_RELOCATION_TABLE = 6,  // Emit ELF relocation table for X86.
+    // DEPCREATED: ELF relocation table for ARM.
+    // MAKE_ELF_ARM_RELOCATION_TABLE_DEPRECATED = 7,
     MAKE_PE64_RELOCATION_TABLE = 8,  // Emit PE64 base relocation table blocks.
     ABS64 = 9,  // ABS64 <index> - emit abs64 encoded reference to address at
-                // address table offset <index>
-    // ARM reserves 0x1000-LAST_ARM, bits 13-16 define the opcode
-    // subset, and 1-12 are the compressed ARM op.
-    REL32ARM8 = 0x1000,
-    REL32ARM11 = 0x2000,
-    REL32ARM24 = 0x3000,
-    REL32ARM25 = 0x4000,
-    REL32ARM21 = 0x5000,
-    LAST_ARM = 0x5FFF,
+                // address table offset <index>.
   };
 
   typedef NoThrowBuffer<RVA> RvaVector;
@@ -133,12 +124,6 @@
   CheckBool GenerateElfRelocations(Elf32_Word pending_elf_relocation_table,
                                    SinkStream* buffer) WARN_UNUSED_RESULT;
 
-  // Decodes and evaluates courgette ops for ARM rel32 addresses.
-  CheckBool EvaluateRel32ARM(OP op,
-                             size_t* ix_rel32_ix,
-                             RVA* current_rva,
-                             SinkStream* output);
-
   // Binary assembly language tables.
   uint64_t image_base_ = 0;
   RvaVector rel32_rva_;
diff --git a/courgette/ensemble_apply.cc b/courgette/ensemble_apply.cc
index 9f4ec54..918e6210 100644
--- a/courgette/ensemble_apply.cc
+++ b/courgette/ensemble_apply.cc
@@ -141,7 +141,6 @@
     switch (kind) {
       case EXE_WIN_32_X86:  // Fall through.
       case EXE_ELF_32_X86:
-      case EXE_ELF_32_ARM:
       case EXE_WIN_32_X64:
         patcher.reset(new PatcherX86_32(base_region_));
         break;
diff --git a/courgette/ensemble_create.cc b/courgette/ensemble_create.cc
index c439fac..4e5b7f3 100644
--- a/courgette/ensemble_create.cc
+++ b/courgette/ensemble_create.cc
@@ -85,15 +85,6 @@
               EXE_ELF_32_X86);
       return generator;
     }
-    case EXE_ELF_32_ARM: {
-      TransformationPatchGenerator* generator =
-          new PatchGeneratorX86_32(
-              old_element,
-              new_element,
-              new PatcherX86_32(old_element->region()),
-              EXE_ELF_32_ARM);
-      return generator;
-    }
     case EXE_WIN_32_X64: {
       TransformationPatchGenerator* generator =
           new PatchGeneratorX86_32(
diff --git a/courgette/instruction_utils.h b/courgette/instruction_utils.h
index 32287a9..9b201dce7 100644
--- a/courgette/instruction_utils.h
+++ b/courgette/instruction_utils.h
@@ -26,9 +26,6 @@
   // Generates an ELF style relocation table for X86.
   virtual CheckBool EmitElfRelocation() = 0;
 
-  // Generates an ELF style relocation table for ARM.
-  virtual CheckBool EmitElfARMRelocation() = 0;
-
   // Following instruction will be assembled at address 'rva'.
   virtual CheckBool EmitOrigin(RVA rva) = 0;
 
@@ -41,12 +38,6 @@
   // Generates a 4-byte relative reference to address of 'label'.
   virtual CheckBool EmitRel32(Label* label) = 0;
 
-  // Generates a 4-byte relative reference to address of 'label' for ARM.
-  virtual CheckBool EmitRel32ARM(uint16_t op,
-                                 Label* label,
-                                 const uint8_t* arm_op,
-                                 uint16_t op_size) = 0;
-
   // Generates a 4-byte absolute reference to address of 'label'.
   virtual CheckBool EmitAbs32(Label* label) = 0;
 
diff --git a/courgette/program_detector.cc b/courgette/program_detector.cc
index 12461f9..cb4dfde 100644
--- a/courgette/program_detector.cc
+++ b/courgette/program_detector.cc
@@ -5,7 +5,6 @@
 #include "courgette/program_detector.h"
 
 #include "courgette/disassembler.h"
-#include "courgette/disassembler_elf_32_arm.h"
 #include "courgette/disassembler_elf_32_x86.h"
 #include "courgette/disassembler_win32_x64.h"
 #include "courgette/disassembler_win32_x86.h"
@@ -31,11 +30,6 @@
     if (disassembler->ParseHeader())
       return disassembler;
   }
-  if (DisassemblerElf32ARM::QuickDetect(buffer, length)) {
-    disassembler.reset(new DisassemblerElf32ARM(buffer, length));
-    if (disassembler->ParseHeader())
-      return disassembler;
-  }
   return nullptr;
 }
 
diff --git a/courgette/program_detector_unittest.cc b/courgette/program_detector_unittest.cc
index 82c6fdb..ce1e6ea 100644
--- a/courgette/program_detector_unittest.cc
+++ b/courgette/program_detector_unittest.cc
@@ -9,7 +9,6 @@
 #include "courgette/base_test_unittest.h"
 #include "courgette/courgette.h"
 #include "courgette/disassembler.h"
-#include "courgette/disassembler_elf_32_arm.h"
 #include "courgette/disassembler_elf_32_x86.h"
 #include "courgette/disassembler_win32_x64.h"
 #include "courgette/disassembler_win32_x86.h"
@@ -41,10 +40,6 @@
             DisassemblerElf32X86::QuickDetect(
                 reinterpret_cast<const uint8_t*>(test_data.data()),
                 test_data.size()));
-  EXPECT_EQ(expected_type == EXE_ELF_32_ARM,
-            DisassemblerElf32ARM::QuickDetect(
-                reinterpret_cast<const uint8_t*>(test_data.data()),
-                test_data.size()));
 }
 
 void ProgramDetectorTest::TestDetectDisassembler(
@@ -62,17 +57,14 @@
   std::string win32_x86 = FileContents("setup1.exe");
   std::string win32_x64 = FileContents("chrome64_1.exe");
   std::string elf_32 = FileContents("elf-32-1");
-  std::string elf_arm = FileContents("elf-armv7");
 
   TestQuickDetect(win32_x86, EXE_WIN_32_X86);
   TestQuickDetect(win32_x64, EXE_WIN_32_X64);
   TestQuickDetect(elf_32, EXE_ELF_32_X86);
-  TestQuickDetect(elf_arm, EXE_ELF_32_ARM);
 
   TestDetectDisassembler(win32_x86, EXE_WIN_32_X86);
   TestDetectDisassembler(win32_x64, EXE_WIN_32_X64);
   TestDetectDisassembler(elf_32, EXE_ELF_32_X86);
-  TestDetectDisassembler(elf_arm, EXE_ELF_32_ARM);
 }
 
 }  // namespace
diff --git a/courgette/typedrva_unittest.cc b/courgette/typedrva_unittest.cc
index d0ad833..5dd65a4 100644
--- a/courgette/typedrva_unittest.cc
+++ b/courgette/typedrva_unittest.cc
@@ -5,7 +5,6 @@
 #include <stdint.h>
 
 #include "courgette/base_test_unittest.h"
-#include "courgette/disassembler_elf_32_arm.h"
 #include "courgette/disassembler_elf_32_x86.h"
 #include "courgette/image_utils.h"
 
@@ -14,15 +13,6 @@
   void TestRelativeTargetX86(courgette::RVA word, courgette::RVA expected)
     const;
 
-  void TestRelativeTargetARM(courgette::ARM_RVA arm_rva,
-                             courgette::RVA rva,
-                             uint32_t op,
-                             courgette::RVA expected) const;
-
-  void TestARMOPEncode(courgette::ARM_RVA arm_rva,
-                       courgette::RVA rva,
-                       uint32_t op,
-                       courgette::RVA expected) const;
 };
 
 void TypedRVATest::TestRelativeTargetX86(courgette::RVA word,
@@ -41,126 +31,6 @@
   return *reinterpret_cast<const uint32_t*>(address);
 }
 
-void TypedRVATest::TestRelativeTargetARM(courgette::ARM_RVA arm_rva,
-                                         courgette::RVA rva,
-                                         uint32_t op,
-                                         courgette::RVA expected) const {
-  courgette::DisassemblerElf32ARM::TypedRVAARM* typed_rva
-    = new courgette::DisassemblerElf32ARM::TypedRVAARM(arm_rva, rva);
-  uint8_t* op_pointer = reinterpret_cast<uint8_t*>(&op);
-
-  EXPECT_TRUE(typed_rva->ComputeRelativeTarget(op_pointer));
-  EXPECT_EQ(rva + typed_rva->relative_target(), expected);
-
-  delete typed_rva;
-}
-
-void TypedRVATest::TestARMOPEncode(courgette::ARM_RVA arm_rva,
-                                   courgette::RVA rva,
-                                   uint32_t op,
-                                   courgette::RVA expected) const {
-  uint16_t c_op;
-  uint32_t addr;
-  EXPECT_TRUE(courgette::DisassemblerElf32ARM::Compress(arm_rva, op, rva,
-                                                        &c_op, &addr));
-  EXPECT_EQ(rva + addr, expected);
-
-  uint32_t new_op;
-  EXPECT_TRUE(courgette::DisassemblerElf32ARM::Decompress(arm_rva, c_op, addr,
-                                                          &new_op));
-  EXPECT_EQ(new_op, op);
-}
-
 TEST_F(TypedRVATest, TestX86) {
   TestRelativeTargetX86(0x0, 0x4);
 }
-
-// ARM opcodes taken from and tested against the output of
-// "arm-linux-gnueabi-objdump -d daisy_3701.98.0/bin/ls"
-
-TEST_F(TypedRVATest, TestARM_OFF8_PREFETCH) {
-  TestRelativeTargetARM(courgette::ARM_OFF8, 0x0, 0x0, 0x4);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF8_FORWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec);
-  TestRelativeTargetARM(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF8_BACKWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF11_PREFETCH) {
-  TestRelativeTargetARM(courgette::ARM_OFF11, 0x0, 0x0, 0x4);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF11_FORWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF11_BACKWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e);
-  TestRelativeTargetARM(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF24_PREFETCH) {
-  TestRelativeTargetARM(courgette::ARM_OFF24, 0x0, 0x0, 0x8);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF24_FORWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874);
-  TestRelativeTargetARM(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8);
-  TestRelativeTargetARM(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF24_BACKWARDS) {
-  // TODO(paulgazz): find a real-world example of an non-thumb ARM
-  // branch op that jumps backwards.
-}
-
-TEST_F(TypedRVATest, TestARM_OFF25_FORWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bf4, 0xfe06f008, 0xb804);
-  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c58, 0xfeacf005, 0x89b4);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF25_BACKWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd2, 0xeb9ef7ff, 0x2310);
-  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd8, 0xeb8ef7ff, 0x22f8);
-  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c3e, 0xea2ef7ff, 0x209c);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF21_FORWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bc6, 0x84c7f000, 0x3558);
-  TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bde, 0x871df000, 0x3a1c);
-  TestRelativeTargetARM(courgette::ARM_OFF21, 0x2c5e, 0x86c1f2c0, 0x39e4);
-}
-
-TEST_F(TypedRVATest, TestARM_OFF21_BACKWARDS) {
-  TestRelativeTargetARM(courgette::ARM_OFF21, 0x67e4, 0xaee9f43f, 0x65ba);
-  TestRelativeTargetARM(courgette::ARM_OFF21, 0x67ee, 0xaee4f47f, 0x65ba);
-}
-
-TEST_F(TypedRVATest, TestARMOPEncode) {
-  TestARMOPEncode(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec);
-  TestARMOPEncode(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776);
-  TestARMOPEncode(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764);
-  TestARMOPEncode(courgette::ARM_OFF11, 0x0, 0x0, 0x4);
-  TestARMOPEncode(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8);
-  TestARMOPEncode(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e);
-  TestARMOPEncode(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8);
-  TestARMOPEncode(courgette::ARM_OFF24, 0x0, 0x0, 0x8);
-  TestARMOPEncode(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874);
-  TestARMOPEncode(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8);
-  TestARMOPEncode(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468);
-  TestARMOPEncode(courgette::ARM_OFF25, 0x2bf4, 0xf008fe06, 0xb804);
-  TestARMOPEncode(courgette::ARM_OFF25, 0x2c58, 0xf005feac, 0x89b4);
-  TestARMOPEncode(courgette::ARM_OFF25, 0x2bd2, 0xf7ffeb9e, 0x2310);
-  TestARMOPEncode(courgette::ARM_OFF25, 0x2bd8, 0xf7ffeb8e, 0x22f8);
-  TestARMOPEncode(courgette::ARM_OFF25, 0x2c3e, 0xf7ffea2e, 0x209c);
-  TestARMOPEncode(courgette::ARM_OFF21, 0x2bc6, 0xf00084c7, 0x3558);
-  TestARMOPEncode(courgette::ARM_OFF21, 0x2bde, 0xf000871d, 0x3a1c);
-  TestARMOPEncode(courgette::ARM_OFF21, 0x2c5e, 0xf2c086c1, 0x39e4);
-  TestARMOPEncode(courgette::ARM_OFF21, 0x67e4, 0xf43faee9, 0x65ba);
-  TestARMOPEncode(courgette::ARM_OFF21, 0x67ee, 0xf47faee4, 0x65ba);
-}
diff --git a/courgette/types_elf.h b/courgette/types_elf.h
index d45a10e..78c67a07d9 100644
--- a/courgette/types_elf.h
+++ b/courgette/types_elf.h
@@ -173,8 +173,4 @@
   R_386_TLS_TPOFF = 14,
 };
 
-enum elf32_rel_arm_type_values {
-  R_ARM_RELATIVE = 23,
-};
-
 #endif  // COURGETTE_ELF_TYPES_H_
diff --git a/docs/README.md b/docs/README.md
index 8cb77cd..cdc5522d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -361,6 +361,7 @@
     install Chromium OS on VMWare.
 *   [User Data Directory](user_data_dir.md) - How the user data and cache
     directories are determined on all platforms.
+*   [User Data Storage](user_data_storage.md) - Policy documentation for files in User Data.
 
 ### Mojo &amp; Services
 *   [Intro to Mojo &amp; Services](mojo_and_services.md) - Quick introduction
diff --git a/docs/testing/web_tests.md b/docs/testing/web_tests.md
index 3ab8de8..1201c8f 100644
--- a/docs/testing/web_tests.md
+++ b/docs/testing/web_tests.md
@@ -13,6 +13,12 @@
 Please assume these terms mean the identical stuff. We also call it as
 "WebKit tests" and "WebKit layout tests".
 
+["Web platform tests"](./web_platform_tests.md) (WPT) are the preferred form of
+web tests and are located at
+[web_tests/external/wpt](/third_party/blink/web_tests/external/wpt).
+Tests that should work across browsers go there. Other directories are for
+Chrome-specific tests only.
+
 [TOC]
 
 ## Running Web Tests
@@ -581,11 +587,6 @@
 3. Request review of the CL and tell the reviewer to compare the patch sets that
    were uploaded in step 1 and step 2 to see the differences of the rebaselines.
 
-## web-platform-tests
-
-In addition to web tests developed and run just by the Blink team, there is
-also a shared test suite, see [web-platform-tests](./web_platform_tests.md).
-
 ## Known Issues
 
 See
diff --git a/docs/user_data_storage.md b/docs/user_data_storage.md
new file mode 100644
index 0000000..67eb9513
--- /dev/null
+++ b/docs/user_data_storage.md
@@ -0,0 +1,46 @@
+# User Data Storage
+
+This document explains the Chromium policies for files in the `User Data`
+directory.
+
+[TOC]
+
+## Backward Compatibility
+
+Due to the nature of frequent updates, Chromium must always support loading data
+from files written by previous versions. A good rule of thumb is to leave
+migration code in place for *at least* one year (approximately 9 milestones with
+the current 6-week release cadence). It is not uncommon for clients to update
+from very old versions, so use good judgement for deciding when to remove
+migration code -- if the complexity is low, keep it indefinitely.
+
+## Version Downgrade Processing
+
+In cases where Chromium is run against a `User Data` directory written by a
+newer version, the browser may run to the extent possible with the following
+behaviors:
+
+*   Versioned files that are apparently readable by the old version may be used
+    as-is and modified as needed. For example, a SQLite file containing a table
+    with a compatible version number no higher than that supported by the old
+    version.
+*   Versioned files that cannot be read by the old version and contain user
+    configuration or user generated data are left on-disk unmodified. This
+    allows the data to be used again once the browser is updated. Furthermore,
+    the user should be notified via the [profile error
+    dialog](../chrome/browser/ui/profile_error_dialog.h) that their experience
+    may be degraded. For example, such a browsing session may not accumulate new
+    history database entries.
+*   Versioned files that cannot be read by the old version and contain computed
+    or cached data may be either left on-disk unmodified or deleted and
+    replaced.
+
+## Post-branch Compatibility
+
+Breaking changes in data storage are forbidden once a branch has been created
+for a release. This guarantees that data written by a later build on a release
+branch can be read by previous versions on that same release branch.
+
+## See also
+
+*   [User Data Directory](user_data_dir.md)
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index fde444a..7bd2056 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -1086,8 +1086,7 @@
 
 void ExtensionDownloader::OnExtensionLoadComplete(base::FilePath crx_path) {
   GURL url = extension_loader_->GetFinalURL();
-  net::URLRequestStatus status =
-      net::URLRequestStatus::FromError(extension_loader_->NetError());
+  int net_error = extension_loader_->NetError();
   int response_code = -1;
   if (extension_loader_->ResponseInfo() &&
       extension_loader_->ResponseInfo()->headers) {
@@ -1118,8 +1117,8 @@
       NotifyDelegateDownloadFinished(std::move(fetch_data), false, crx_path,
                                      true);
     }
-  } else if (IterateFetchCredentialsAfterFailure(
-                 &active_request, status, response_code)) {
+  } else if (IterateFetchCredentialsAfterFailure(&active_request,
+                                                 response_code)) {
     delegate_->OnExtensionDownloadStageChanged(
         id, ExtensionDownloaderDelegate::Stage::DOWNLOADING_CRX_RETRY);
     extensions_queue_.RetryRequest(backoff_delay);
@@ -1139,8 +1138,8 @@
       RETRY_HISTOGRAM("CrxFetchFailure",
                       extensions_queue_.active_request_failure_count(),
                       url);
-      // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h)
-      base::UmaHistogramSparse("Extensions.CrxFetchError", -status.error());
+      // 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);
       delegate_->OnExtensionDownloadFailed(
@@ -1188,7 +1187,6 @@
 
 bool ExtensionDownloader::IterateFetchCredentialsAfterFailure(
     ExtensionFetch* fetch,
-    const net::URLRequestStatus& status,
     int response_code) {
   bool auth_failure = response_code == net::HTTP_UNAUTHORIZED ||
                       response_code == net::HTTP_FORBIDDEN;
diff --git a/extensions/browser/updater/extension_downloader.h b/extensions/browser/updater/extension_downloader.h
index 9857dd9..b9ed82f3 100644
--- a/extensions/browser/updater/extension_downloader.h
+++ b/extensions/browser/updater/extension_downloader.h
@@ -37,10 +37,6 @@
 struct AccessTokenInfo;
 }  // namespace signin
 
-namespace net {
-class URLRequestStatus;
-}
-
 namespace network {
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
@@ -338,7 +334,6 @@
   // |true| if the fetch should be retried. Returns |false| if the failure was
   // not related to authentication, leaving the ExtensionFetch data unmodified.
   bool IterateFetchCredentialsAfterFailure(ExtensionFetch* fetch,
-                                           const net::URLRequestStatus& status,
                                            int response_code);
 
   void OnAccessTokenFetchComplete(GoogleServiceAuthError error,
diff --git a/fuchsia/engine/browser/ax_tree_converter.cc b/fuchsia/engine/browser/ax_tree_converter.cc
index f082eff5..a35da0b 100644
--- a/fuchsia/engine/browser/ax_tree_converter.cc
+++ b/fuchsia/engine/browser/ax_tree_converter.cc
@@ -91,10 +91,10 @@
 
 fuchsia::ui::gfx::BoundingBox ConvertBoundingBox(gfx::RectF bounds) {
   fuchsia::ui::gfx::BoundingBox box;
-  float min[3] = {bounds.bottom_left().x(), bounds.bottom_left().y(), 0.0f};
-  float max[3] = {bounds.top_right().x(), bounds.top_right().y(), 0.0f};
-  box.min = scenic::NewVector3(min);
-  box.max = scenic::NewVector3(max);
+  box.min = scenic::NewVector3({bounds.bottom_left().x(),
+                                bounds.bottom_left().y(), 0.0f});
+  box.max = scenic::NewVector3({bounds.top_right().x(), bounds.top_right().y(),
+                                0.0f});
   return box;
 }
 
@@ -102,8 +102,8 @@
 // subtree as an optimization to handle resizing or repositioning. This requires
 // only one node to be updated on such an event.
 fuchsia::ui::gfx::mat4 ConvertTransform(gfx::Transform* transform) {
-  float mat[16] = {};
-  transform->matrix().asColMajorf(mat);
+  std::array<float, 16> mat = {};
+  transform->matrix().asColMajorf(mat.data());
   fuchsia::ui::gfx::Matrix4Value fuchsia_transform =
       scenic::NewMatrix4Value(mat);
   return fuchsia_transform.value;
diff --git a/fuchsia/engine/browser/ax_tree_converter_unittest.cc b/fuchsia/engine/browser/ax_tree_converter_unittest.cc
index 1baf9cc..3dc1ad72 100644
--- a/fuchsia/engine/browser/ax_tree_converter_unittest.cc
+++ b/fuchsia/engine/browser/ax_tree_converter_unittest.cc
@@ -26,8 +26,8 @@
 const int32_t kRectY = 2;
 const int32_t kRectWidth = 7;
 const int32_t kRectHeight = 8;
-const float k4DIdentityMatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0,
-                                     0, 0, 1, 0, 0, 0, 0, 1};
+const std::array<float, 16> k4DIdentityMatrix = {1, 0, 0, 0, 0, 1, 0, 0,
+                                                 0, 0, 1, 0, 0, 0, 0, 1};
 
 bool SemanticNodesAreEqual(const Node& first, const Node& second) {
   if (first.node_id() != second.node_id())
@@ -128,10 +128,8 @@
   Attributes attributes;
   attributes.set_label(kLabel1);
   fuchsia::ui::gfx::BoundingBox box;
-  float min[3] = {kRectX, kRectY + kRectHeight, 0.0f};
-  float max[3] = {kRectHeight, kRectY, 0.0f};
-  box.min = scenic::NewVector3(min);
-  box.max = scenic::NewVector3(max);
+  box.min = scenic::NewVector3({kRectX, kRectY + kRectHeight, 0.0f});
+  box.max = scenic::NewVector3({kRectHeight, kRectY, 0.0f});
   fuchsia::ui::gfx::Matrix4Value mat =
       scenic::NewMatrix4Value(k4DIdentityMatrix);
   auto expected_node = CreateSemanticNode(
@@ -179,8 +177,8 @@
   Attributes attributes;
   attributes.set_label(kLabel1);
   fuchsia::ui::gfx::BoundingBox box;
-  float min[3] = {kRectX, kRectY + kRectHeight, 0.0f};
-  float max[3] = {kRectHeight, kRectY, 0.0f};
+  std::array<float, 3> min = {kRectX, kRectY + kRectHeight, 0.0f};
+  std::array<float, 3> max = {kRectHeight, kRectY, 0.0f};
   box.min = scenic::NewVector3(min);
   box.max = scenic::NewVector3(max);
   fuchsia::ui::gfx::Matrix4Value mat =
diff --git a/infra/config/buckets/ci.star b/infra/config/buckets/ci.star
index a6dc301..08506f4 100644
--- a/infra/config/buckets/ci.star
+++ b/infra/config/buckets/ci.star
@@ -343,11 +343,11 @@
 )
 
 android_fyi_builder(
-    name = 'Android WebView P FYI (rel)',
+    name = 'Android WebView P Blink-CORS FYI (rel)',
 )
 
 android_fyi_builder(
-    name = 'Android WebView P OOR-CORS FYI (rel)',
+    name = 'Android WebView P FYI (rel)',
 )
 
 android_fyi_builder(
@@ -1087,6 +1087,10 @@
 )
 
 fyi_builder(
+    name = 'linux-blink-cors-rel',
+)
+
+fyi_builder(
     name = 'linux-blink-heap-concurrent-marking-tsan-rel',
 )
 
@@ -1107,10 +1111,6 @@
 )
 
 fyi_builder(
-    name = 'linux-oor-cors-rel',
-)
-
-fyi_builder(
     name = 'linux-wpt-fyi-rel',
     experimental = True,
     goma_backend = None
diff --git a/infra/config/buckets/try.star b/infra/config/buckets/try.star
index dbe211a..ef32e46 100644
--- a/infra/config/buckets/try.star
+++ b/infra/config/buckets/try.star
@@ -184,9 +184,7 @@
     cores = 16,
     goma_jobs = goma.jobs.J300,
     ssd = True,
-    tryjob = tryjob(
-        experiment_percentage = 100,
-    ),
+    tryjob = tryjob(),
 )
 
 android_builder(
diff --git a/infra/config/consoles/chromium.android.fyi.star b/infra/config/consoles/chromium.android.fyi.star
index d3596e5..75f5fab 100644
--- a/infra/config/consoles/chromium.android.fyi.star
+++ b/infra/config/consoles/chromium.android.fyi.star
@@ -8,16 +8,16 @@
             category = 'android',
         ),
         luci.console_view_entry(
+            builder = 'ci/Android WebView P Blink-CORS FYI (rel)',
+            category = 'webview',
+            short_name = 'cors',
+        ),
+        luci.console_view_entry(
             builder = 'ci/Android WebView P FYI (rel)',
             category = 'webview',
             short_name = 'p-rel',
         ),
         luci.console_view_entry(
-            builder = 'ci/Android WebView P OOR-CORS FYI (rel)',
-            category = 'webview',
-            short_name = 'cors',
-        ),
-        luci.console_view_entry(
             builder = 'ci/android-marshmallow-x86-fyi-rel',
             category = 'emulator|M|x86',
             short_name = 'rel',
diff --git a/infra/config/consoles/chromium.android.star b/infra/config/consoles/chromium.android.star
index ddf15887..d27286d 100644
--- a/infra/config/consoles/chromium.android.star
+++ b/infra/config/consoles/chromium.android.star
@@ -188,7 +188,7 @@
         ),
         luci.console_view_entry(
             builder = 'ci/android-pie-arm64-rel',
-            category = 'on_cq|future',
+            category = 'on_cq',
             short_name = 'P',
         ),
     ],
diff --git a/infra/config/consoles/chromium.fyi.star b/infra/config/consoles/chromium.fyi.star
index 81696605..5b29e4f 100644
--- a/infra/config/consoles/chromium.fyi.star
+++ b/infra/config/consoles/chromium.fyi.star
@@ -145,7 +145,7 @@
             category = 'linux',
         ),
         luci.console_view_entry(
-            builder = 'ci/linux-oor-cors-rel',
+            builder = 'ci/linux-blink-cors-rel',
             category = 'linux',
         ),
         luci.console_view_entry(
diff --git a/infra/config/consoles/chromium.goma.migration.star b/infra/config/consoles/chromium.goma.migration.star
index 0aa168969..4d6798d 100644
--- a/infra/config/consoles/chromium.goma.migration.star
+++ b/infra/config/consoles/chromium.goma.migration.star
@@ -722,17 +722,17 @@
             short_name = 'bfc',
         ),
         luci.console_view_entry(
+            builder = 'ci/linux-blink-cors-rel',
+            category = 'week15a|linux',
+            short_name = 'oorcors',
+        ),
+        luci.console_view_entry(
             builder = 'ci/linux-fieldtrial-rel',
             category = 'week15a|linux',
             short_name = 'field',
         ),
         luci.console_view_entry(
-            builder = 'ci/linux-oor-cors-rel',
-            category = 'week15a|linux',
-            short_name = 'oorcors',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Android WebView P OOR-CORS FYI (rel)',
+            builder = 'ci/Android WebView P Blink-CORS FYI (rel)',
             category = 'week15b|android|webview p',
             short_name = 'oorcors',
         ),
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 08872a2..27100cdd 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -89,7 +89,6 @@
       >
       builders: <
         name: "chromium/try/android-pie-arm64-rel"
-        experiment_percentage: 100
       >
       builders: <
         name: "chromium/try/android-pie-x86-fyi-rel"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index c1bb1ba..612daba 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -19,6 +19,8 @@
 
 * [android-marshmallow-arm64-rel](https://ci.chromium.org/p/chromium/builders/try/android-marshmallow-arm64-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-marshmallow-arm64-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-marshmallow-arm64-rel))
 
+* [android-pie-arm64-rel](https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-pie-arm64-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-pie-arm64-rel))
+
 * [android_compile_dbg](https://ci.chromium.org/p/chromium/builders/try/android_compile_dbg) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android_compile_dbg)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android_compile_dbg))
 
 * [android_cronet](https://ci.chromium.org/p/chromium/builders/try/android_cronet) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android_cronet)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android_cronet))
@@ -315,9 +317,6 @@
 by CQ. These are often used to test new configurations before they are added
 as required builders.
 
-* [android-pie-arm64-rel](https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-pie-arm64-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-pie-arm64-rel))
-  * Experiment percentage: 100
-
 * [fuchsia-compile-x64-dbg](https://ci.chromium.org/p/chromium/builders/try/fuchsia-compile-x64-dbg) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+fuchsia-compile-x64-dbg)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+fuchsia-compile-x64-dbg))
   * Experiment percentage: 50
 
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index dd51f79..9121ebe6 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -650,7 +650,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     >
     builders: <
-      name: "Android WebView P FYI (rel)"
+      name: "Android WebView P Blink-CORS FYI (rel)"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builderless:1"
@@ -671,7 +671,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     >
     builders: <
-      name: "Android WebView P OOR-CORS FYI (rel)"
+      name: "Android WebView P FYI (rel)"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builderless:1"
@@ -7031,6 +7031,27 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     >
     builders: <
+      name: "linux-blink-cors-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "ssd:0"
+      recipe: <
+        name: "chromium"
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        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\""
+      >
+      execution_timeout_secs: 36000
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+    >
+    builders: <
       name: "linux-blink-heap-concurrent-marking-tsan-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -7244,27 +7265,6 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     >
     builders: <
-      name: "linux-oor-cors-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04"
-      dimensions: "ssd:0"
-      recipe: <
-        name: "chromium"
-        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
-        cipd_version: "refs/heads/master"
-        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\""
-      >
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
-    >
-    builders: <
       name: "linux-ozone-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 43fdfde..c18cf6b 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -812,7 +812,7 @@
   >
   builders: <
     name: "buildbucket/luci.chromium.ci/android-pie-arm64-rel"
-    category: "on_cq|future"
+    category: "on_cq"
     short_name: "P"
   >
   header: <
@@ -1074,16 +1074,16 @@
     category: "android"
   >
   builders: <
+    name: "buildbucket/luci.chromium.ci/Android WebView P Blink-CORS FYI (rel)"
+    category: "webview"
+    short_name: "cors"
+  >
+  builders: <
     name: "buildbucket/luci.chromium.ci/Android WebView P FYI (rel)"
     category: "webview"
     short_name: "p-rel"
   >
   builders: <
-    name: "buildbucket/luci.chromium.ci/Android WebView P OOR-CORS FYI (rel)"
-    category: "webview"
-    short_name: "cors"
-  >
-  builders: <
     name: "buildbucket/luci.chromium.ci/android-marshmallow-x86-fyi-rel"
     category: "emulator|M|x86"
     short_name: "rel"
@@ -3038,7 +3038,7 @@
     category: "linux"
   >
   builders: <
-    name: "buildbucket/luci.chromium.ci/linux-oor-cors-rel"
+    name: "buildbucket/luci.chromium.ci/linux-blink-cors-rel"
     category: "linux"
   >
   builders: <
@@ -5157,17 +5157,17 @@
     short_name: "bfc"
   >
   builders: <
+    name: "buildbucket/luci.chromium.ci/linux-blink-cors-rel"
+    category: "week15a|linux"
+    short_name: "oorcors"
+  >
+  builders: <
     name: "buildbucket/luci.chromium.ci/linux-fieldtrial-rel"
     category: "week15a|linux"
     short_name: "field"
   >
   builders: <
-    name: "buildbucket/luci.chromium.ci/linux-oor-cors-rel"
-    category: "week15a|linux"
-    short_name: "oorcors"
-  >
-  builders: <
-    name: "buildbucket/luci.chromium.ci/Android WebView P OOR-CORS FYI (rel)"
+    name: "buildbucket/luci.chromium.ci/Android WebView P Blink-CORS FYI (rel)"
     category: "week15b|android|webview p"
     short_name: "oorcors"
   >
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index ec2fc20..c8a7b8e 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -69,8 +69,8 @@
   triggers: "ASan Release Media (32-bit x86 with V8-ARM)"
   triggers: "Afl Upload Linux ASan"
   triggers: "Android ASAN (dbg)"
+  triggers: "Android WebView P Blink-CORS FYI (rel)"
   triggers: "Android WebView P FYI (rel)"
-  triggers: "Android WebView P OOR-CORS FYI (rel)"
   triggers: "android-archive-dbg-goma-canary"
   triggers: "android-archive-dbg-goma-latest"
   triggers: "android-archive-dbg-goma-rbe-canary"
@@ -358,8 +358,8 @@
   triggers: "ios13-sdk-simulator"
   triggers: "linux-annotator-rel"
   triggers: "linux-bfcache-debug"
-  triggers: "linux-oor-cors-rel"
   triggers: "linux-blink-animation-use-time-delta"
+  triggers: "linux-blink-cors-rel"
   triggers: "linux-blink-heap-concurrent-marking-tsan-rel"
   triggers: "linux-blink-heap-verification"
   triggers: "linux-chromeos-dbg"
@@ -783,6 +783,16 @@
 }
 
 job {
+  id: "Android WebView P Blink-CORS FYI (rel)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android WebView P Blink-CORS FYI (rel)"
+  }
+}
+
+job {
   id: "Android WebView P FYI (rel)"
   acl_sets: "default"
   buildbucket: {
@@ -793,16 +803,6 @@
 }
 
 job {
-  id: "Android WebView P OOR-CORS FYI (rel)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android WebView P OOR-CORS FYI (rel)"
-  }
-}
-
-job {
   id: "Android x64 Builder (dbg)"
   acl_sets: "default"
   buildbucket: {
@@ -2607,12 +2607,12 @@
 }
 
 job {
-  id: "linux-oor-cors-rel"
+  id: "linux-blink-cors-rel"
   acl_sets: "default"
   buildbucket: {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.chromium.ci"
-    builder: "linux-oor-cors-rel"
+    builder: "linux-blink-cors-rel"
   }
 }
 
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg
index ec2fc20..c8a7b8e 100644
--- a/infra/config/luci-scheduler.cfg
+++ b/infra/config/luci-scheduler.cfg
@@ -69,8 +69,8 @@
   triggers: "ASan Release Media (32-bit x86 with V8-ARM)"
   triggers: "Afl Upload Linux ASan"
   triggers: "Android ASAN (dbg)"
+  triggers: "Android WebView P Blink-CORS FYI (rel)"
   triggers: "Android WebView P FYI (rel)"
-  triggers: "Android WebView P OOR-CORS FYI (rel)"
   triggers: "android-archive-dbg-goma-canary"
   triggers: "android-archive-dbg-goma-latest"
   triggers: "android-archive-dbg-goma-rbe-canary"
@@ -358,8 +358,8 @@
   triggers: "ios13-sdk-simulator"
   triggers: "linux-annotator-rel"
   triggers: "linux-bfcache-debug"
-  triggers: "linux-oor-cors-rel"
   triggers: "linux-blink-animation-use-time-delta"
+  triggers: "linux-blink-cors-rel"
   triggers: "linux-blink-heap-concurrent-marking-tsan-rel"
   triggers: "linux-blink-heap-verification"
   triggers: "linux-chromeos-dbg"
@@ -783,6 +783,16 @@
 }
 
 job {
+  id: "Android WebView P Blink-CORS FYI (rel)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android WebView P Blink-CORS FYI (rel)"
+  }
+}
+
+job {
   id: "Android WebView P FYI (rel)"
   acl_sets: "default"
   buildbucket: {
@@ -793,16 +803,6 @@
 }
 
 job {
-  id: "Android WebView P OOR-CORS FYI (rel)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android WebView P OOR-CORS FYI (rel)"
-  }
-}
-
-job {
   id: "Android x64 Builder (dbg)"
   acl_sets: "default"
   buildbucket: {
@@ -2607,12 +2607,12 @@
 }
 
 job {
-  id: "linux-oor-cors-rel"
+  id: "linux-blink-cors-rel"
   acl_sets: "default"
   buildbucket: {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.chromium.ci"
-    builder: "linux-oor-cors-rel"
+    builder: "linux-blink-cors-rel"
   }
 }
 
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn
index 5e9de3a..e42118e 100644
--- a/ios/chrome/browser/flags/BUILD.gn
+++ b/ios/chrome/browser/flags/BUILD.gn
@@ -49,6 +49,7 @@
     "//ios/chrome/browser/ui/dialogs:feature_flags",
     "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/infobars:feature_flags",
+    "//ios/chrome/browser/ui/page_info:features",
     "//ios/chrome/browser/ui/settings/autofill:feature_flags",
     "//ios/chrome/browser/ui/table_view:feature_flags",
     "//ios/chrome/browser/ui/toolbar/public:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 5048761..0089d9d 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -60,6 +60,7 @@
 #import "ios/chrome/browser/ui/dialogs/dialog_features.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+#import "ios/chrome/browser/ui/page_info/features.h"
 #include "ios/chrome/browser/ui/settings/autofill/features.h"
 #import "ios/chrome/browser/ui/table_view/feature_flags.h"
 #import "ios/chrome/browser/ui/toolbar/public/features.h"
@@ -606,7 +607,9 @@
     {"reload-sad-tab", flag_descriptions::kReloadSadTabName,
      flag_descriptions::kReloadSadTabDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(web::kReloadSadTab)},
-};
+    {"page-info-refactoring", flag_descriptions::kPageInfoRefactoringName,
+     flag_descriptions::kPageInfoRefactoringDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kPageInfoRefactoring)}};
 
 // Add all switches from experimental flags to |command_line|.
 void AppendSwitchesFromExperimentalSettings(base::CommandLine* command_line) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index a787fbf..a07b8b3 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -307,6 +307,10 @@
     "Shows Google head non personalized search suggestions provided by a "
     "compact on device model";
 
+const char kPageInfoRefactoringName[] = "New design of the page info";
+const char kPageInfoRefactoringDescription[] =
+    "Uses the new design for the page security info.";
+
 const char kPasswordLeakDetectionName[] = "Password Leak Detection";
 const char kPasswordLeakDetectionDescription[] =
     "Enables the detection of leaked passwords.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 87cdc63..c51c062 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -264,6 +264,10 @@
 extern const char kOmniboxOnDeviceHeadSuggestionsName[];
 extern const char kOmniboxOnDeviceHeadSuggestionsDescription[];
 
+// Title and description for the flag to enable the new design of the page info.
+extern const char kPageInfoRefactoringName[];
+extern const char kPageInfoRefactoringDescription[];
+
 // Title and description for the flag to enable leak detection for entered
 // credentials.
 extern const char kPasswordLeakDetectionName[];
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn
index c31fdee..e99d615 100644
--- a/ios/chrome/browser/main/BUILD.gn
+++ b/ios/chrome/browser/main/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/infobars:feature_flags",
     "//ios/chrome/browser/web_state_list",
+    "//ios/public/provider/chrome/browser",
   ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/chrome/browser/main/browser_agent_util.mm b/ios/chrome/browser/main/browser_agent_util.mm
index afe94b6..4eec336f 100644
--- a/ios/chrome/browser/main/browser_agent_util.mm
+++ b/ios/chrome/browser/main/browser_agent_util.mm
@@ -10,6 +10,7 @@
 #import "ios/chrome/browser/infobars/infobar_badge_browser_agent.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
 #import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -24,4 +25,7 @@
   if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) {
     InfobarBadgeBrowserAgent::CreateForBrowser(browser);
   }
+  // This needs to be called last in case any downstream browser agents need to
+  // access upstream agents created earlier in this function.
+  ios::GetChromeBrowserProvider()->AttachBrowserAgents(browser);
 }
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
index 0c129f5..535e9f31 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
+++ b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
@@ -4,6 +4,8 @@
 
 source_set("infobar_banner") {
   sources = [
+    "infobar_banner_overlay_responses.cc",
+    "infobar_banner_overlay_responses.h",
     "save_password_infobar_banner_overlay.h",
     "save_password_infobar_banner_overlay.mm",
   ]
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc
new file mode 100644
index 0000000..75603b2
--- /dev/null
+++ b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc
@@ -0,0 +1,31 @@
+// 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 "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h"
+
+#pragma mark - InfobarBannerMainActionResponse
+
+OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerMainActionResponse);
+
+InfobarBannerMainActionResponse::InfobarBannerMainActionResponse() = default;
+
+InfobarBannerMainActionResponse::~InfobarBannerMainActionResponse() = default;
+
+#pragma mark - InfobarBannerShowModalResponse
+
+OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerShowModalResponse);
+
+InfobarBannerShowModalResponse::InfobarBannerShowModalResponse() = default;
+
+InfobarBannerShowModalResponse::~InfobarBannerShowModalResponse() = default;
+
+#pragma mark - InfobarBannerCompletionResponse
+
+OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerCompletionResponse);
+
+InfobarBannerCompletionResponse::InfobarBannerCompletionResponse(
+    bool user_initiated)
+    : user_initiated_(user_initiated) {}
+
+InfobarBannerCompletionResponse::~InfobarBannerCompletionResponse() = default;
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h
new file mode 100644
index 0000000..9bf87b8f
--- /dev/null
+++ b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h
@@ -0,0 +1,52 @@
+// 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 IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_RESPONSES_H_
+#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_RESPONSES_H_
+
+#include "ios/chrome/browser/overlays/public/overlay_response_info.h"
+
+// Response info used to create dispatched OverlayResponses that trigger the
+// infobar's main action.
+class InfobarBannerMainActionResponse
+    : public OverlayResponseInfo<InfobarBannerMainActionResponse> {
+ public:
+  ~InfobarBannerMainActionResponse() override;
+
+ private:
+  OVERLAY_USER_DATA_SETUP(InfobarBannerMainActionResponse);
+  InfobarBannerMainActionResponse();
+};
+
+// Response info used to create dispatched OverlayResponses that trigger the
+// presentation of the infobar's modal.
+class InfobarBannerShowModalResponse
+    : public OverlayResponseInfo<InfobarBannerShowModalResponse> {
+ public:
+  ~InfobarBannerShowModalResponse() override;
+
+ private:
+  OVERLAY_USER_DATA_SETUP(InfobarBannerShowModalResponse);
+  InfobarBannerShowModalResponse();
+};
+
+// Response info used to create completion OverlayResponses for an infobar
+// banner OverlayRequest.  Executed when the banner is dismissed by the user or
+// the request is cancelled.
+class InfobarBannerCompletionResponse
+    : public OverlayResponseInfo<InfobarBannerCompletionResponse> {
+ public:
+  ~InfobarBannerCompletionResponse() override;
+
+  // Whether the banner dismissal was user-initiated.
+  bool user_initiated() const { return user_initiated_; }
+
+ private:
+  OVERLAY_USER_DATA_SETUP(InfobarBannerCompletionResponse);
+  explicit InfobarBannerCompletionResponse(bool user_initiated);
+
+  bool user_initiated_ = false;
+};
+
+#endif  // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_RESPONSES_H_
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h
index 09d5db8..a80db00 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h
+++ b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h
@@ -21,10 +21,16 @@
  public:
   ~SavePasswordInfobarBannerOverlayRequestConfig() override;
 
-  // The save password delegate used to configure the banner UI.
-  IOSChromeSavePasswordInfoBarDelegate* save_password_delegate() const {
-    return save_password_delegate_;
-  }
+  // The infobar delegate's message text.
+  NSString* message() const { return message_; }
+  // The username for which passwords are being saved.
+  NSString* username() const { return username_; }
+  // The text to show on the banner's confirm button.
+  NSString* button_text() const { return button_text_; }
+  // The name of the banner's icon image.
+  NSString* icon_image_name() const { return icon_image_name_; }
+  // The length of the password being saved.
+  size_t password_length() const { return password_length_; }
 
  private:
   OVERLAY_USER_DATA_SETUP(SavePasswordInfobarBannerOverlayRequestConfig);
@@ -36,8 +42,12 @@
 
   // The InfoBar causing this banner.
   infobars::InfoBar* infobar_ = nullptr;
-  // The delegate used to configure the save passwords banner.
-  IOSChromeSavePasswordInfoBarDelegate* save_password_delegate_ = nullptr;
+  // Configuration data extracted from |infobar_|'s save passwords delegate.
+  NSString* message_ = nil;
+  NSString* username_ = nil;
+  NSString* button_text_ = nil;
+  NSString* icon_image_name_ = nil;
+  size_t password_length_ = 0;
 };
 
 #endif  // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_SAVE_PASSWORD_INFOBAR_BANNER_OVERLAY_H_
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
index fad8764..fedca22 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
+++ b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
@@ -5,17 +5,10 @@
 #import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
 
 #include "base/logging.h"
-#include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
 #include "components/infobars/core/infobar.h"
-#include "ios/chrome/browser/infobars/infobar_ios.h"
-#import "ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.h"
 #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
 #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
-#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h"
-#include "ios/chrome/grit/ios_strings.h"
-#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -32,12 +25,17 @@
 
 SavePasswordInfobarBannerOverlayRequestConfig::
     SavePasswordInfobarBannerOverlayRequestConfig(InfoBar* infobar)
-    : infobar_(infobar),
-      save_password_delegate_(
-          IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
-              infobar->delegate())) {
+    : infobar_(infobar) {
   DCHECK(infobar_);
-  DCHECK(save_password_delegate_);
+  IOSChromeSavePasswordInfoBarDelegate* delegate =
+      IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
+          infobar_->delegate());
+  message_ = base::SysUTF16ToNSString(delegate->GetMessageText());
+  username_ = delegate->GetUserNameText();
+  button_text_ = base::SysUTF16ToNSString(
+      delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
+  icon_image_name_ = kIconImageName;
+  password_length_ = delegate->GetPasswordText().length;
 }
 
 SavePasswordInfobarBannerOverlayRequestConfig::
@@ -46,28 +44,4 @@
 void SavePasswordInfobarBannerOverlayRequestConfig::CreateAuxilliaryData(
     base::SupportsUserData* user_data) {
   InfobarOverlayRequestConfig::CreateForUserData(user_data, infobar_);
-  InfobarOverlayRequestConfig* infobar_config =
-      InfobarOverlayRequestConfig::FromUserData(user_data);
-  // Use the save passwords delegate to configure the request for its banner UI.
-  NSString* title_text =
-      base::SysUTF16ToNSString(save_password_delegate_->GetMessageText());
-  NSString* username = save_password_delegate_->GetUserNameText();
-  NSString* password = save_password_delegate_->GetPasswordText();
-  password = [@"" stringByPaddingToLength:[password length]
-                               withString:@"•"
-                          startingAtIndex:0];
-  NSString* subtitle_text =
-      [NSString stringWithFormat:@"%@ %@", username, password];
-  NSString* button_text =
-      base::SysUTF16ToNSString(save_password_delegate_->GetButtonLabel(
-          ConfirmInfoBarDelegate::BUTTON_OK));
-  NSString* hidden_password_text =
-      l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL);
-  NSString* banner_accessibility_label =
-      [NSString stringWithFormat:@"%@,%@, %@", title_text, username,
-                                 hidden_password_text];
-  bool presents_modal = infobar_config->has_badge();
-  InfobarBannerOverlayRequestConfig::CreateForUserData(
-      user_data, banner_accessibility_label, button_text, kIconImageName,
-      presents_modal, title_text, subtitle_text);
 }
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h
index eddbd492..8801a4dc 100644
--- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h
+++ b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h
@@ -43,11 +43,11 @@
   bool IsTabPinned(int index) const override;
   base::Optional<tab_groups::TabGroupId> GetTabGroupForTab(
       int index) const override;
-  tab_groups::TabGroupVisualData* GetVisualDataForGroup(
-      tab_groups::TabGroupId group) const override;
+  const tab_groups::TabGroupVisualData* GetVisualDataForGroup(
+      const tab_groups::TabGroupId& group) const override;
   void SetVisualDataForGroup(
-      tab_groups::TabGroupId group,
-      tab_groups::TabGroupVisualData visual_data) override;
+      const tab_groups::TabGroupId& group,
+      const tab_groups::TabGroupVisualData& visual_data) override;
   const gfx::Rect GetRestoredBounds() const override;
   ui::WindowShowState GetRestoredState() const override;
   std::string GetWorkspace() const override;
@@ -57,7 +57,7 @@
       int selected_navigation,
       const std::string& extension_app_id,
       base::Optional<tab_groups::TabGroupId> group,
-      const tab_groups::TabGroupVisualData group_visual_data,
+      const tab_groups::TabGroupVisualData& group_visual_data,
       bool select,
       bool pin,
       bool from_last_session,
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
index 6839449..a2c900d 100644
--- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
+++ b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
@@ -79,9 +79,9 @@
   return base::nullopt;
 }
 
-tab_groups::TabGroupVisualData*
+const tab_groups::TabGroupVisualData*
 TabRestoreServiceDelegateImplIOS::GetVisualDataForGroup(
-    tab_groups::TabGroupId group) const {
+    const tab_groups::TabGroupId& group) const {
   // Since we never return a group from GetTabGroupForTab(), this should never
   // be called.
   NOTREACHED();
@@ -89,8 +89,8 @@
 }
 
 void TabRestoreServiceDelegateImplIOS::SetVisualDataForGroup(
-    tab_groups::TabGroupId group,
-    tab_groups::TabGroupVisualData visual_data) {
+    const tab_groups::TabGroupId& group,
+    const tab_groups::TabGroupVisualData& visual_data) {
   // Not supported on iOS.
 }
 
@@ -115,7 +115,7 @@
     int selected_navigation,
     const std::string& extension_app_id,
     base::Optional<tab_groups::TabGroupId> group,
-    const tab_groups::TabGroupVisualData group_visual_data,
+    const tab_groups::TabGroupVisualData& group_visual_data,
     bool select,
     bool pin,
     bool from_last_session,
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index 7e1c21c4..835e9e12 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -118,6 +118,7 @@
     "//ios/chrome/browser/ui/open_in",
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/page_info:coordinator",
+    "//ios/chrome/browser/ui/page_info:features",
     "//ios/chrome/browser/ui/page_info/requirements",
     "//ios/chrome/browser/ui/passwords",
     "//ios/chrome/browser/ui/payments",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index bd94d1bd..186a4af 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
 #import "ios/chrome/browser/autofill/autofill_tab_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/download/download_directory_util.h"
 #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
 #import "ios/chrome/browser/main/browser.h"
@@ -32,9 +33,12 @@
 #import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/infobar_commands.h"
+#import "ios/chrome/browser/ui/commands/page_info_commands.h"
 #import "ios/chrome/browser/ui/download/ar_quick_look_coordinator.h"
 #import "ios/chrome/browser/ui/download/pass_kit_coordinator.h"
 #import "ios/chrome/browser/ui/open_in/open_in_mediator.h"
+#import "ios/chrome/browser/ui/page_info/features.h"
+#import "ios/chrome/browser/ui/page_info/page_info_coordinator.h"
 #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h"
 #import "ios/chrome/browser/ui/passwords/password_breach_coordinator.h"
 #import "ios/chrome/browser/ui/print/print_controller.h"
@@ -62,6 +66,7 @@
 @interface BrowserCoordinator () <AutofillSecurityAlertPresenter,
                                   BrowserCoordinatorCommands,
                                   FormInputAccessoryCoordinatorNavigator,
+                                  PageInfoCommands,
                                   RepostFormTabHelperDelegate,
                                   URLLoadingServiceDelegate,
                                   WebStateListObserving>
@@ -111,7 +116,7 @@
     ManualFillAllPasswordCoordinator* allPasswordCoordinator;
 
 // Coordinator for Page Info UI.
-@property(nonatomic, strong) PageInfoLegacyCoordinator* pageInfoCoordinator;
+@property(nonatomic, strong) ChromeCoordinator* pageInfoCoordinator;
 
 // Coordinator for the PassKit UI presentation.
 @property(nonatomic, strong) PassKitCoordinator* passKitCoordinator;
@@ -178,6 +183,8 @@
   [self.dispatcher
       startDispatchingToTarget:self
                    forProtocol:@protocol(BrowserCoordinatorCommands)];
+  [self.dispatcher startDispatchingToTarget:self
+                                forProtocol:@protocol(PageInfoCommands)];
   [self installDelegatesForAllWebStates];
   [self installDelegatesForBrowserState];
   [self addWebStateListObserver];
@@ -225,6 +232,8 @@
 
   [self.passwordBreachCoordinator stop];
 
+  [self.pageInfoCoordinator stop];
+
   [self.viewController clearPresentedStateWithCompletion:completion
                                           dismissOmnibox:dismissOmnibox];
 }
@@ -311,12 +320,6 @@
                          browser:self.browser];
   [self.translateInfobarCoordinator start];
 
-  self.pageInfoCoordinator = [[PageInfoLegacyCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                         browser:self.browser];
-  self.pageInfoCoordinator.presentationProvider = self.viewController;
-  [self.pageInfoCoordinator start];
-
   self.passKitCoordinator = [[PassKitCoordinator alloc]
       initWithBaseViewController:self.viewController];
 
@@ -485,6 +488,41 @@
   [self.addCreditCardCoordinator start];
 }
 
+#pragma mark - PageInfoCommands
+
+- (void)legacyShowPageInfoForOriginPoint:(CGPoint)originPoint {
+  PageInfoLegacyCoordinator* pageInfoCoordinator =
+      [[PageInfoLegacyCoordinator alloc]
+          initWithBaseViewController:self.viewController
+                             browser:self.browser];
+  pageInfoCoordinator.presentationProvider = self.viewController;
+  pageInfoCoordinator.originPoint = originPoint;
+  self.pageInfoCoordinator = pageInfoCoordinator;
+  [self.pageInfoCoordinator start];
+}
+
+- (void)showPageInfo {
+  DCHECK(base::FeatureList::IsEnabled(kPageInfoRefactoring));
+  PageInfoCoordinator* pageInfoCoordinator = [[PageInfoCoordinator alloc]
+      initWithBaseViewController:self.viewController
+                         browser:self.browser];
+  pageInfoCoordinator.presentationProvider = self.viewController;
+  self.pageInfoCoordinator = pageInfoCoordinator;
+  [self.pageInfoCoordinator start];
+}
+
+- (void)hidePageInfo {
+  [self.pageInfoCoordinator stop];
+  self.pageInfoCoordinator = nil;
+}
+
+- (void)showSecurityHelpPage {
+  UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kPageInfoHelpCenterURL));
+  params.in_incognito = self.browserState->IsOffTheRecord();
+  UrlLoadingServiceFactory::GetForBrowserState(self.browserState)->Load(params);
+  [self hidePageInfo];
+}
+
 #pragma mark - FormInputAccessoryCoordinatorNavigator
 
 - (void)openPasswordSettings {
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 a6cec0e..12507f9 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1267,7 +1267,6 @@
     [self.dispatcher cancelOmniboxEdit];
   }
   [_dialogPresenter cancelAllDialogs];
-  [self.dispatcher hidePageInfo];
   [self.bubblePresenter dismissBubbles];
   if (_voiceSearchController)
     _voiceSearchController->DismissMicPermissionsHelp();
diff --git a/ios/chrome/browser/ui/commands/page_info_commands.h b/ios/chrome/browser/ui/commands/page_info_commands.h
index 4c7607f..7657616 100644
--- a/ios/chrome/browser/ui/commands/page_info_commands.h
+++ b/ios/chrome/browser/ui/commands/page_info_commands.h
@@ -11,14 +11,18 @@
 // Commands related to the Page Info UI.
 @protocol PageInfoCommands
 
-// Show the page security info. |originPoint| is the midpoint of the UI element
+// TODO(crbug.com/1038923): Remove this command.
+// Shows the page security info. |originPoint| is the midpoint of the UI element
 // which triggered this command and should be in window coordinates.
-- (void)showPageInfoForOriginPoint:(CGPoint)originPoint;
+- (void)legacyShowPageInfoForOriginPoint:(CGPoint)originPoint;
 
-// Hide the page security info.
+// Shows the page security info.
+- (void)showPageInfo;
+
+// Hides the page security info.
 - (void)hidePageInfo;
 
-// Show the security help page.
+// Shows the security help page.
 - (void)showSecurityHelpPage;
 
 @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
index aa096f97..3c5cc7b 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -159,6 +159,18 @@
 - (void)invalidateLayout {
   [self updateFakeOmniboxOnNewWidth:self.collectionView.bounds.size.width];
   [self.collectionView.collectionViewLayout invalidateLayout];
+
+  if (@available(iOS 13, *)) {
+    dispatch_async(dispatch_get_main_queue(), ^{
+      // On iOS 13, invalidating the layout doesn't reset the positioning of the
+      // header. To make sure that it is correctly positioned, scroll 1pt. This
+      // is done in the next runloop to have the collectionView resized and the
+      // content offset set to the new value. See crbug.com/1025694.
+      CGPoint currentOffset = [self.collectionView contentOffset];
+      currentOffset.y += 1;
+      [self.collectionView setContentOffset:currentOffset animated:YES];
+    });
+  }
 }
 
 #pragma mark - ContentSuggestionsHeaderSynchronizing
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h
index 6042ec1..601ad67 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h
@@ -5,7 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_CONSUMER_H_
 #define IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_CONSUMER_H_
 
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
 
 @protocol InfobarBannerConsumer <NSObject>
 
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
index 33891e9..bddedbc 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
@@ -5,7 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_DELEGATE_H_
 #define IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_DELEGATE_H_
 
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
 
 // Delegate to handle InfobarBanner actions.
 @protocol InfobarBannerDelegate
diff --git a/ios/chrome/browser/ui/infobars/banners/test/BUILD.gn b/ios/chrome/browser/ui/infobars/banners/test/BUILD.gn
new file mode 100644
index 0000000..dd71e84
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/banners/test/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test") {
+  testonly = true
+  sources = [
+    "fake_infobar_banner_consumer.h",
+    "fake_infobar_banner_consumer.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    "//base",
+    "//ios/chrome/browser/ui/infobars/banners",
+  ]
+}
diff --git a/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h
new file mode 100644
index 0000000..2c4421e
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_TEST_FAKE_INFOBAR_BANNER_CONSUMER_H_
+#define IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_TEST_FAKE_INFOBAR_BANNER_CONSUMER_H_
+
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h"
+
+// Fake InfobarBannerConsumer used in tests.
+@interface FakeInfobarBannerConsumer : NSObject <InfobarBannerConsumer>
+// Redefine InfobarBannerConsumer properties as readwrite.
+@property(nonatomic, copy) NSString* bannerAccessibilityLabel;
+@property(nonatomic, copy) NSString* buttonText;
+@property(nonatomic, strong) UIImage* iconImage;
+@property(nonatomic, assign) BOOL presentsModal;
+@property(nonatomic, copy) NSString* titleText;
+@property(nonatomic, copy) NSString* subtitleText;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_TEST_FAKE_INFOBAR_BANNER_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm
new file mode 100644
index 0000000..4fe97c0b
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.mm
@@ -0,0 +1,12 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation FakeInfobarBannerConsumer
+@end
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm
index 1246cda..12abf12 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm
@@ -420,18 +420,6 @@
   // TODO(crbug.com/1014959): implement else logic. Should aything be done?
 }
 
-#pragma mark - InfobarTranslateLanguageSelectionDelegate
-
-- (void)didSelectSourceLanguageIndex:(int)languageIndex
-                            withName:(NSString*)languageName {
-  // TODO(crbug.com/1014959): Implement.
-}
-
-- (void)didSelectTargetLanguageIndex:(int)languageIndex
-                            withName:(NSString*)languageName {
-  // TODO(crbug.com/1014959): Implement.
-}
-
 #pragma mark - Private
 
 // Helper method for performInfobarAction, which also allows for
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_mediator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_mediator.mm
index 13f001f..e55124d 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_mediator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_mediator.mm
@@ -186,9 +186,9 @@
 
   base::string16 targetLanguage =
       self.translateInfobarDelegate->target_language_name();
-  if (self.newSourceLanguageIndex != kInvalidLanguageIndex) {
+  if (self.newTargetLanguageIndex != kInvalidLanguageIndex) {
     targetLanguage = self.translateInfobarDelegate->language_name_at(
-        self.newSourceLanguageIndex);
+        self.newTargetLanguageIndex);
   }
   [self.modalConsumer
       setupModalViewControllerWithPrefs:
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
index 2287095..e75dc57 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -337,9 +337,7 @@
     // as if the pre-edit fake selection was real.
     [field_ exitPreEditState];
 
-    field_.selectedTextRange =
-        [field_ textRangeFromPosition:field_.beginningOfDocument
-                           toPosition:field_.endOfDocument];
+    field_.text = @"";
 
     // Reset |range| to be of zero-length at location zero, as the field will be
     // now cleared.
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn
index 6611898..6da865d 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn
@@ -12,5 +12,68 @@
 
   configs += [ "//build/config/compiler:enable_arc" ]
 
-  deps = []
+  deps = [
+    ":coordinators",
+  ]
+}
+
+source_set("coordinators") {
+  sources = [
+    "infobar_banner_overlay_coordinator.h",
+    "infobar_banner_overlay_coordinator.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    ":mediators",
+    "//base",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/common/infobars",
+    "//ios/chrome/browser/ui/infobars/banners",
+    "//ios/chrome/browser/ui/overlays:coordinators",
+    "//ios/chrome/browser/ui/overlays/infobar_banner/passwords",
+  ]
+}
+
+source_set("mediators") {
+  sources = [
+    "infobar_banner_overlay_mediator+consumer_support.h",
+    "infobar_banner_overlay_mediator.h",
+    "infobar_banner_overlay_mediator.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    "//base",
+    "//components/infobars/core",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/ui/infobars/banners",
+    "//ios/chrome/browser/ui/infobars/banners:public",
+    "//ios/chrome/browser/ui/overlays:coordinators",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "infobar_banner_overlay_mediator_unittest.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    ":mediators",
+    "//components/infobars/core",
+    "//ios/chrome/browser/infobars/test",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/overlays/test",
+    "//ios/chrome/browser/ui/overlays/test",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base",
+  ]
 }
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.h b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.h
new file mode 100644
index 0000000..3e3add8
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.h
@@ -0,0 +1,14 @@
+// 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 IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_COORDINATOR_H_
+
+#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h"
+
+// A coordinator that displays infobar banner UI using OverlayPresenter.
+@interface InfobarBannerOverlayCoordinator : OverlayRequestCoordinator
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm
new file mode 100644
index 0000000..19e52fdb
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm
@@ -0,0 +1,140 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/no_destructor.h"
+#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
+#import "ios/chrome/browser/overlays/public/overlay_request.h"
+#import "ios/chrome/browser/overlays/public/overlay_request_support.h"
+#import "ios/chrome/browser/overlays/public/overlay_response.h"
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_accessibility_util.h"
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h"
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
+#import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator+subclassing.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator_delegate.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Creates a vector containing the OverlayRequestSupports for each
+// OverlayRequestMediator class in |mediator_classes|
+const std::vector<const OverlayRequestSupport*> GetSupportsForMediatorClasses(
+    NSArray<Class>* mediator_classes) {
+  std::vector<const OverlayRequestSupport*> supports(mediator_classes.count);
+  for (NSUInteger index = 0; index < mediator_classes.count; ++index) {
+    supports[index] = [mediator_classes[index] requestSupport];
+  }
+  return supports;
+}
+}  // namespace
+
+@interface InfobarBannerOverlayCoordinator ()
+// The list of supported mediator classes.
+@property(class, nonatomic, readonly) NSArray<Class>* supportedMediatorClasses;
+// The banner view being managed by this coordinator.
+@property(nonatomic) InfobarBannerViewController* bannerViewController;
+@end
+
+@implementation InfobarBannerOverlayCoordinator
+
+#pragma mark - Accessors
+
++ (NSArray<Class>*)supportedMediatorClasses {
+  return @ [[SavePasswordInfobarBannerOverlayMediator class]];
+}
+
++ (const OverlayRequestSupport*)requestSupport {
+  static std::unique_ptr<const OverlayRequestSupport> _requestSupport;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    _requestSupport = std::make_unique<OverlayRequestSupport>(
+        GetSupportsForMediatorClasses(self.supportedMediatorClasses));
+  });
+  return _requestSupport.get();
+}
+
+#pragma mark - OverlayRequestCoordinator
+
+- (void)startAnimated:(BOOL)animated {
+  if (self.started || !self.request)
+    return;
+  // Create the mediator and use it aas the delegate for the banner view.
+  InfobarOverlayRequestConfig* config =
+      self.request->GetConfig<InfobarOverlayRequestConfig>();
+  InfobarBannerOverlayMediator* mediator = [self newMediator];
+  self.bannerViewController = [[InfobarBannerViewController alloc]
+      initWithDelegate:mediator
+         presentsModal:config->has_badge()
+                  type:config->infobar_type()];
+  mediator.consumer = self.bannerViewController;
+  self.mediator = mediator;
+  // Present the banner.
+  // TODO(crbug.com/1030357): Use custom presentation.
+  self.bannerViewController.modalPresentationStyle =
+      UIModalPresentationOverCurrentContext;
+  self.bannerViewController.modalTransitionStyle =
+      UIModalTransitionStyleCrossDissolve;
+  [self.baseViewController presentViewController:self.viewController
+                                        animated:animated
+                                      completion:^{
+                                        [self finishPresentation];
+                                      }];
+  self.started = YES;
+}
+
+- (void)stopAnimated:(BOOL)animated {
+  if (!self.started)
+    return;
+  [self.baseViewController dismissViewControllerAnimated:animated
+                                              completion:^{
+                                                [self finishDismissal];
+                                              }];
+  self.started = NO;
+}
+
+- (UIViewController*)viewController {
+  return self.bannerViewController;
+}
+
+#pragma mark - Private
+
+// Called when the presentation of the banner UI is completed.
+- (void)finishPresentation {
+  // Notify the presentation context that the presentation has finished.  This
+  // is necessary to synchronize OverlayPresenter scheduling logic with the UI
+  // layer.
+  self.delegate->OverlayUIDidFinishPresentation(self.request);
+  UpdateBannerAccessibilityForPresentation(self.baseViewController,
+                                           self.viewController.view);
+}
+
+// Called when the dismissal of the banner UI is finished.
+- (void)finishDismissal {
+  self.bannerViewController = nil;
+  self.mediator = nil;
+  // Notify the presentation context that the dismissal has finished.  This
+  // is necessary to synchronize OverlayPresenter scheduling logic with the UI
+  // layer.
+  self.delegate->OverlayUIDidFinishDismissal(self.request);
+  UpdateBannerAccessibilityForDismissal(self.baseViewController);
+}
+
+// Creates a mediator instance from the supported mediator class list that
+// supports the coordinator's request.
+- (InfobarBannerOverlayMediator*)newMediator {
+  for (Class mediatorClass in [self class].supportedMediatorClasses) {
+    if (mediatorClass.requestSupport->IsRequestSupported(self.request))
+      return [[mediatorClass alloc] initWithRequest:self.request];
+  }
+  NOTREACHED() << "None of the supported mediator classes support request.";
+  return nil;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h
new file mode 100644
index 0000000..6561216
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h
@@ -0,0 +1,20 @@
+// 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 IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_CONSUMER_SUPPORT_H_
+#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_CONSUMER_SUPPORT_H_
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
+
+// Category used by the InfobarBannerOverlayMediator superclass in order to
+// configure its consumer.
+@interface InfobarBannerOverlayMediator (ConsumerSupport)
+
+// Sets up the banner consumer using the configuration information from the
+// mediator's OverlayRequest.  Subclasses must implement.
+- (void)configureConsumer;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_CONSUMER_SUPPORT_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h
new file mode 100644
index 0000000..db2d895
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h
@@ -0,0 +1,23 @@
+// 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 IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_mediator.h"
+
+@protocol InfobarBannerConsumer;
+
+// Mediator superclass for configuring InfobarBannerConsumers.
+@interface InfobarBannerOverlayMediator
+    : OverlayRequestMediator <InfobarBannerDelegate>
+
+// The consumer to be updated by this mediator.  Setting to a new value updates
+// the new consumer.
+@property(nonatomic, weak) id<InfobarBannerConsumer> consumer;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
new file mode 100644
index 0000000..720cbbd7
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
@@ -0,0 +1,93 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
+
+#import <UIKit/UIKit.h>
+
+#include "base/logging.h"
+#import "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h"
+#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
+#include "ios/chrome/browser/overlays/public/overlay_request.h"
+#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h"
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation InfobarBannerOverlayMediator
+
+- (instancetype)initWithRequest:(OverlayRequest*)request {
+  if (self = [super initWithRequest:request]) {
+    DCHECK([self class].requestSupport->IsRequestSupported(request));
+  }
+  return self;
+}
+
+#pragma mark - Accessors
+
+- (void)setConsumer:(id<InfobarBannerConsumer>)consumer {
+  if (_consumer == consumer)
+    return;
+  _consumer = consumer;
+  if (_consumer)
+    [self configureConsumer];
+}
+
+#pragma mark - InfobarBannerDelegate
+
+- (void)bannerInfobarButtonWasPressed:(UIButton*)sender {
+  // Notify the model layer to perform the infobar's main action before
+  // dismissing the banner.
+  [self dispatchResponseAndStopOverlay:OverlayResponse::CreateWithInfo<
+                                           InfobarBannerMainActionResponse>()];
+}
+
+- (void)dismissInfobarBannerForUserInteraction:(BOOL)userInitiated {
+  if (self.request) {
+    // Add a completion response notifying the requesting code of whether the
+    // dismissal was user-initiated.  Provided to the request's completion
+    // callbacks that are executed when the UI is finished being dismissed.
+    self.request->GetCallbackManager()->SetCompletionResponse(
+        OverlayResponse::CreateWithInfo<InfobarBannerCompletionResponse>(
+            userInitiated));
+  }
+  [self.delegate stopOverlayForMediator:self];
+}
+
+- (void)presentInfobarModalFromBanner {
+  // Notify the model layer to show the infobar modal before dismissing the
+  // banner.
+  [self dispatchResponseAndStopOverlay:OverlayResponse::CreateWithInfo<
+                                           InfobarBannerShowModalResponse>()];
+}
+
+- (void)infobarBannerWasDismissed {
+  // Only needed in legacy implementation.  Dismissal completion cleanup occurs
+  // in InfobarBannerOverlayCoordinator.
+}
+
+#pragma mark - Private
+
+// Dispatches |response| through the OverlayRequest, then stops the overlay UI.
+- (void)dispatchResponseAndStopOverlay:
+    (std::unique_ptr<OverlayResponse>)response {
+  if (self.request)
+    self.request->GetCallbackManager()->DispatchResponse(std::move(response));
+  [self.delegate stopOverlayForMediator:self];
+}
+
+@end
+
+@implementation InfobarBannerOverlayMediator (ConsumerSupport)
+
+- (void)configureConsumer {
+  NOTREACHED() << "Subclasses must implement.";
+}
+
+@end
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator_unittest.mm
new file mode 100644
index 0000000..65fcdc30
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator_unittest.mm
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
+
+#import "base/bind.h"
+#include "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h"
+#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
+#include "ios/chrome/browser/overlays/public/overlay_dispatch_callback.h"
+#include "ios/chrome/browser/overlays/public/overlay_request.h"
+#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// InfobarBannerOverlayMediator subclass used for testing.
+@interface FakeInfobarBannerOverlayMediator : InfobarBannerOverlayMediator
+@end
+
+@implementation FakeInfobarBannerOverlayMediator
++ (const OverlayRequestSupport*)requestSupport {
+  return OverlayRequestSupport::All();
+}
+@end
+
+// Test fixture for InfobarBannerOverlayMediator.
+class InfobarBannerOverlayMediatorTest : public PlatformTest {
+ public:
+  InfobarBannerOverlayMediatorTest()
+      : request_(OverlayRequest::CreateWithConfig<FakeOverlayUserData>()),
+        delegate_(
+            OCMStrictProtocolMock(@protocol(OverlayRequestMediatorDelegate))),
+        mediator_([[FakeInfobarBannerOverlayMediator alloc]
+            initWithRequest:request_.get()]) {
+    mediator_.delegate = delegate_;
+  }
+  ~InfobarBannerOverlayMediatorTest() override {
+    EXPECT_OCMOCK_VERIFY(delegate_);
+  }
+
+ protected:
+  std::unique_ptr<OverlayRequest> request_;
+  id<OverlayRequestMediatorDelegate> delegate_ = nil;
+  InfobarBannerOverlayMediator* mediator_ = nil;
+};
+
+// Tests that an InfobarBannerOverlayMediator correctly dispatches a response
+// for confirm button taps before stopping itself.
+TEST_F(InfobarBannerOverlayMediatorTest, ConfirmButtonTapped) {
+  __block bool confirm_button_tapped = false;
+  void (^confirm_button_tapped_callback)(OverlayResponse* response) =
+      ^(OverlayResponse* response) {
+        confirm_button_tapped = true;
+      };
+  request_->GetCallbackManager()->AddDispatchCallback(OverlayDispatchCallback(
+      base::BindRepeating(confirm_button_tapped_callback),
+      InfobarBannerMainActionResponse::ResponseSupport()));
+  ASSERT_FALSE(confirm_button_tapped);
+
+  // Notify the mediator of the button tap via its InfobarBannerDelegate
+  // implementation and verify that the confirm button callback was executed and
+  // that the mediator's delegate was instructed to stop.
+  OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
+  [mediator_ bannerInfobarButtonWasPressed:nil];
+  EXPECT_TRUE(confirm_button_tapped);
+}
+
+// Tests that an InfobarBannerOverlayMediator correctly dispatches a response
+// for modal button taps before stopping itself.
+TEST_F(InfobarBannerOverlayMediatorTest, ModalButtonTapped) {
+  __block bool modal_button_tapped = false;
+  void (^modal_button_tapped_callback)(OverlayResponse* response) =
+      ^(OverlayResponse* response) {
+        modal_button_tapped = true;
+      };
+  request_->GetCallbackManager()->AddDispatchCallback(OverlayDispatchCallback(
+      base::BindRepeating(modal_button_tapped_callback),
+      InfobarBannerShowModalResponse::ResponseSupport()));
+  ASSERT_FALSE(modal_button_tapped);
+
+  // Notify the mediator of the button tap via its InfobarBannerDelegate
+  // implementation and verify that the modal button callback was executed and
+  // that the mediator's delegate was instructed to stop.
+  OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
+  [mediator_ presentInfobarModalFromBanner];
+  EXPECT_TRUE(modal_button_tapped);
+}
+
+// Tests that an InfobarBannerOverlayMediator correctly sets the completion
+// response for user-initiated dismissals triggered by the banner UI.
+TEST_F(InfobarBannerOverlayMediatorTest, UserInitiatedDismissal) {
+  __block bool user_initiated = false;
+  void (^completion_callback)(OverlayResponse* response) =
+      ^(OverlayResponse* response) {
+        user_initiated = true;
+      };
+  request_->GetCallbackManager()->AddCompletionCallback(
+      base::BindOnce(completion_callback));
+  ASSERT_FALSE(user_initiated);
+
+  // Notify the mediator of the dismissal via its InfobarBannerDelegate
+  // implementation and verify that the completion callback was executed with
+  // the correct info and that the mediator's delegate was instructed to stop.
+  OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
+  [mediator_ dismissInfobarBannerForUserInteraction:YES];
+  request_ = nullptr;
+  EXPECT_TRUE(user_initiated);
+}
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_supported_overlay_coordinator_classes.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_supported_overlay_coordinator_classes.mm
index 2653799..9f1f81e 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_supported_overlay_coordinator_classes.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_supported_overlay_coordinator_classes.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_supported_overlay_coordinator_classes.h"
 
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -11,8 +13,7 @@
 namespace infobar_banner {
 
 NSArray<Class>* GetSupportedOverlayCoordinatorClasses() {
-  // TODO(crbug.com/1030357): Add overlay coordinator classes when converted.
-  return @[];
+  return @ [[InfobarBannerOverlayCoordinator class]];
 }
 
 }  // infobar_banner
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn
new file mode 100644
index 0000000..3ee22a9
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn
@@ -0,0 +1,54 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("passwords") {
+  sources = [
+    "save_password_infobar_banner_overlay_mediator.h",
+    "save_password_infobar_banner_overlay_mediator.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    "//base",
+    "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/ui/infobars/banners",
+    "//ios/chrome/browser/ui/overlays/infobar_banner:mediators",
+    "//ui/base",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "save_password_infobar_banner_overlay_mediator_unittest.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    ":passwords",
+    "//base/test:test_support",
+    "//components/autofill/core/common",
+    "//components/infobars/core",
+    "//components/password_manager/core/browser:test_support",
+    "//components/strings:components_strings_grit",
+    "//components/url_formatter",
+    "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/overlays/test",
+    "//ios/chrome/browser/passwords:infobar_delegates",
+    "//ios/chrome/browser/ui/infobars:feature_flags",
+    "//ios/chrome/browser/ui/infobars/banners/test",
+    "//ios/chrome/browser/ui/infobars/test",
+    "//ios/chrome/browser/ui/overlays/test",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//ui/base",
+  ]
+}
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h
new file mode 100644
index 0000000..104a0999
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_SAVE_PASSWORD_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_SAVE_PASSWORD_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
+
+// Mediator that configures an infobar banner for a save passwords infobar.
+@interface SavePasswordInfobarBannerOverlayMediator
+    : InfobarBannerOverlayMediator
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_SAVE_PASSWORD_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.mm
new file mode 100644
index 0000000..daa23731
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.mm
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h"
+
+#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
+#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
+#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h"
+#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface SavePasswordInfobarBannerOverlayMediator ()
+// The save password banner config from the request.
+@property(nonatomic, readonly)
+    SavePasswordInfobarBannerOverlayRequestConfig* config;
+@end
+
+@implementation SavePasswordInfobarBannerOverlayMediator
+
+#pragma mark - Accessors
+
+- (SavePasswordInfobarBannerOverlayRequestConfig*)config {
+  return self.request
+             ? self.request
+                   ->GetConfig<SavePasswordInfobarBannerOverlayRequestConfig>()
+             : nullptr;
+}
+
+#pragma mark - OverlayRequestMediator
+
++ (const OverlayRequestSupport*)requestSupport {
+  return SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport();
+}
+
+@end
+
+@implementation SavePasswordInfobarBannerOverlayMediator (ConsumerSupport)
+
+- (void)configureConsumer {
+  SavePasswordInfobarBannerOverlayRequestConfig* config = self.config;
+  if (!self.consumer || !config)
+    return;
+
+  NSString* title = config->message();
+  NSString* username = config->username();
+  NSString* password = [@"" stringByPaddingToLength:config->password_length()
+                                         withString:@"•"
+                                    startingAtIndex:0];
+  NSString* bannerAccessibilityLabel =
+      [NSString stringWithFormat:@"%@, %@, %@", title, username,
+                                 l10n_util::GetNSString(
+                                     IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
+  [self.consumer setBannerAccessibilityLabel:bannerAccessibilityLabel];
+  [self.consumer setButtonText:config->button_text()];
+  [self.consumer setIconImage:[UIImage imageNamed:config->icon_image_name()]];
+  [self.consumer setPresentsModal:YES];
+  [self.consumer setTitleText:title];
+  [self.consumer
+      setSubtitleText:[NSString stringWithFormat:@"%@ %@", username, password]];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
new file mode 100644
index 0000000..ce815de
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
@@ -0,0 +1,97 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h"
+
+#include "base/feature_list.h"
+#include "base/strings/string16.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/infobars/core/infobar.h"
+#include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
+#include "ios/chrome/browser/infobars/infobar_ios.h"
+#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
+#include "ios/chrome/browser/overlays/public/overlay_request.h"
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
+#import "ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h"
+#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
+#include "ios/chrome/grit/ios_strings.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Constants used in tests.
+NSString* const kUsername = @"username";
+NSString* const kPassword = @"12345";
+}
+
+// Test fixture for SavePasswordInfobarBannerOverlayMediator.
+class SavePasswordInfobarBannerOverlayMediatorTest : public PlatformTest {
+ public:
+  SavePasswordInfobarBannerOverlayMediatorTest() {
+    feature_list_.InitWithFeatures({kInfobarUIReboot}, {});
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Tests that a SavePasswordInfobarBannerOverlayMediator correctly sets up its
+// consumer.
+TEST_F(SavePasswordInfobarBannerOverlayMediatorTest, SetUpConsumer) {
+  // Create an InfoBarIOS with a IOSChromeSavePasswordInfoBarDelegate.
+  FakeInfobarUIDelegate* ui_delegate = [[FakeInfobarUIDelegate alloc] init];
+  ui_delegate.infobarType = InfobarType::kInfobarTypePasswordSave;
+  std::unique_ptr<password_manager::MockPasswordFormManagerForUI> form_manager =
+      std::make_unique<password_manager::MockPasswordFormManagerForUI>();
+  autofill::PasswordForm form;
+  form.username_value = base::SysNSStringToUTF16(kUsername);
+  form.password_value = base::SysNSStringToUTF16(kPassword);
+  EXPECT_CALL(*form_manager, GetPendingCredentials())
+      .WillRepeatedly(testing::ReturnRef(form));
+  std::unique_ptr<IOSChromeSavePasswordInfoBarDelegate> passed_delegate =
+      std::make_unique<IOSChromeSavePasswordInfoBarDelegate>(
+          false, false, std::move(form_manager));
+  IOSChromeSavePasswordInfoBarDelegate* delegate = passed_delegate.get();
+  InfoBarIOS infobar(ui_delegate, std::move(passed_delegate));
+  // Package the infobar into an OverlayRequest, then create a mediator that
+  // uses this request in order to set up a fake consumer.
+  std::unique_ptr<OverlayRequest> request = OverlayRequest::CreateWithConfig<
+      SavePasswordInfobarBannerOverlayRequestConfig>(&infobar);
+  SavePasswordInfobarBannerOverlayMediator* mediator =
+      [[SavePasswordInfobarBannerOverlayMediator alloc]
+          initWithRequest:request.get()];
+  FakeInfobarBannerConsumer* consumer =
+      [[FakeInfobarBannerConsumer alloc] init];
+  mediator.consumer = consumer;
+  // Verify that the infobar was set up properly.
+  NSString* title = base::SysUTF16ToNSString(delegate->GetMessageText());
+  NSString* password = [@"" stringByPaddingToLength:kPassword.length
+                                         withString:@"•"
+                                    startingAtIndex:0];
+  NSString* subtitle =
+      [NSString stringWithFormat:@"%@ %@", kUsername, password];
+  NSString* bannerAccessibilityLabel =
+      [NSString stringWithFormat:@"%@, %@, %@", title, kUsername,
+                                 l10n_util::GetNSString(
+                                     IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
+  EXPECT_NSEQ(bannerAccessibilityLabel, consumer.bannerAccessibilityLabel);
+  EXPECT_NSEQ(base::SysUTF16ToNSString(
+                  delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)),
+              consumer.buttonText);
+  EXPECT_NSEQ(title, consumer.titleText);
+  EXPECT_NSEQ(subtitle, consumer.subtitleText);
+  EXPECT_NSEQ([UIImage imageNamed:@"infobar_passwords_icon"],
+              consumer.iconImage);
+  EXPECT_TRUE(consumer.presentsModal);
+}
diff --git a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
index a93a24a7..c11d32be 100644
--- a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
+++ b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
@@ -28,7 +28,7 @@
     "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/location_bar:notifications",
-    "//ios/chrome/browser/ui/page_info:coordinator",
+    "//ios/chrome/browser/ui/page_info:constants",
     "//ios/chrome/browser/ui/side_swipe",
     "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index 0ea5d9d8..265f3a5f 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -18,7 +18,7 @@
 #import "ios/chrome/browser/ui/location_bar/location_bar_notification_names.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_gesture_recognizer.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_view.h"
-#import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h"
+#import "ios/chrome/browser/ui/page_info/page_info_constants.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
 #include "ios/chrome/browser/ui/util/rtl_geometry.h"
 #include "ios/chrome/browser/ui/util/uikit_ui_util.h"
diff --git a/ios/chrome/browser/ui/page_info/BUILD.gn b/ios/chrome/browser/ui/page_info/BUILD.gn
index 529472c..8731a2b 100644
--- a/ios/chrome/browser/ui/page_info/BUILD.gn
+++ b/ios/chrome/browser/ui/page_info/BUILD.gn
@@ -5,9 +5,10 @@
 source_set("page_info") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "legacy_page_info_view_controller.h",
+    "legacy_page_info_view_controller.mm",
     "page_info_model.cc",
     "page_info_model.h",
-    "page_info_model_observer.h",
     "page_info_view_controller.h",
     "page_info_view_controller.mm",
   ]
@@ -49,9 +50,22 @@
   ]
 }
 
+source_set("features") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "features.h",
+    "features.mm",
+  ]
+  deps = [
+    "//base",
+  ]
+}
+
 source_set("coordinator") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "page_info_coordinator.h",
+    "page_info_coordinator.mm",
     "page_info_legacy_coordinator.h",
     "page_info_legacy_coordinator.mm",
   ]
diff --git a/ios/chrome/browser/ui/page_info/features.h b/ios/chrome/browser/ui/page_info/features.h
new file mode 100644
index 0000000..d7f791d
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/features.h
@@ -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.
+
+#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_FEATURES_H_
+#define IOS_CHROME_BROWSER_UI_PAGE_INFO_FEATURES_H_
+
+#include "base/feature_list.h"
+
+// Feature to enable the new design of the page info.
+extern const base::Feature kPageInfoRefactoring;
+
+#endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_FEATURES_H_
diff --git a/ios/chrome/browser/ui/page_info/features.mm b/ios/chrome/browser/ui/page_info/features.mm
new file mode 100644
index 0000000..4d48b3f
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/features.mm
@@ -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.
+
+#import "ios/chrome/browser/ui/page_info/features.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+const base::Feature kPageInfoRefactoring{"PageInfoRefactoring",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.h b/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.h
new file mode 100644
index 0000000..3157236
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_LEGACY_PAGE_INFO_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_PAGE_INFO_LEGACY_PAGE_INFO_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+
+@protocol BrowserCommands;
+@protocol PageInfoPresentation;
+class PageInfoModel;
+
+// TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in
+// upstream; check if we should use PageInfoModel.
+// The view controller for the page info view.
+@interface LegacyPageInfoViewController : NSObject
+// Designated initializer.
+// The |sourcePoint| parameter should be in the coordinate system of
+// |provider|'s view. Typically, |sourcePoint| would be the midpoint of a button
+// that resulted in this popup being displayed.
+- (id)initWithModel:(PageInfoModel*)model
+             sourcePoint:(CGPoint)sourcePoint
+    presentationProvider:(id<PageInfoPresentation>)provider
+                 handler:(id<BrowserCommands>)handler;
+
+// Dispatcher for this view controller.
+@property(nonatomic, weak) id<BrowserCommands> handler;
+
+// Dismisses the view.
+- (void)dismiss;
+
+// Layout the page info view.
+- (void)performLayout;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_LEGACY_PAGE_INFO_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.mm b/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.mm
new file mode 100644
index 0000000..05a51fc1
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.mm
@@ -0,0 +1,573 @@
+// 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.
+
+#import "ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/mac/bundle_locations.h"
+#import "base/mac/foundation_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/browser/ui/fancy_ui/bidi_container_view.h"
+#import "ios/chrome/browser/ui/page_info/page_info_constants.h"
+#include "ios/chrome/browser/ui/page_info/page_info_model.h"
+#import "ios/chrome/browser/ui/page_info/requirements/page_info_presentation.h"
+#import "ios/chrome/browser/ui/util/animation_util.h"
+#include "ios/chrome/browser/ui/util/rtl_geometry.h"
+#include "ios/chrome/browser/ui/util/ui_util.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/UIColor+cr_semantic_colors.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
+#import "ios/chrome/common/material_timing.h"
+#include "ios/chrome/grit/ios_strings.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#import "ui/gfx/ios/NSString+CrStringDrawing.h"
+#import "ui/gfx/ios/uikit_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using ios::material::TimingFunction;
+
+namespace {
+
+// The width of the view.
+const CGFloat kViewWidthRegular = 600.0;
+const CGFloat kViewWidthCompact = 288.0;
+const CGFloat kViewWidthiPhoneLandscape = 400.0;
+// Spacing in between sections.
+const CGFloat kVerticalSpacing = 20.0;
+// Initial position for the left side of the frame.
+const CGFloat kInitialFramePosition = 8.0;
+// Alpha for the shield.
+const CGFloat kShieldAlpha = 0.5;
+// Scroll View inset.
+const CGFloat kScrollViewInset = 5.0;
+// The size of the footer (rounded corner and shadow) for page info view.
+const CGFloat kPageInfoViewFooterSize = 15.0;
+// Padding between the window frame and content.
+const CGFloat kFramePadding = 24;
+// Padding for the initial line of the view.
+const CGFloat kInitialLinePadding = 40;
+// Padding between the bottom of the content and the window frame.
+const CGFloat kFrameBottomPadding = 16;
+// Spacing between the optional headline and description text views.
+const CGFloat kHeadlineSpacing = 16;
+// Spacing between the image and the text.
+const CGFloat kImageSpacing = 16;
+// Square size of the image.
+const CGFloat kImageSize = 24;
+// The height of the headline label.
+const CGFloat kHeadlineHeight = 19;
+
+inline UIFont* PageInfoHeadlineFont() {
+  return [[MDCTypography fontLoader] mediumFontOfSize:16];
+}
+
+inline CATransform3D PageInfoAnimationScale() {
+  return CATransform3DMakeScale(0.03, 0.03, 1);
+}
+
+// Offset to make sure image aligns with the header line.
+inline CGFloat PageInfoImageVerticalOffset() {
+  return ui::AlignValueToUpperPixel((kHeadlineHeight - kImageSize) / 2.0);
+}
+
+// The X position of the text fields. Variants for with and without an image.
+const CGFloat kTextXPositionNoImage = kFramePadding;
+const CGFloat kTextXPosition =
+    kTextXPositionNoImage + kImageSize + kImageSpacing;
+
+// The X offset for the help button.
+const CGFloat kButtonXOffset = kTextXPosition;
+
+}  // namespace
+
+#pragma mark - LegacyPageInfoViewController
+
+@interface LegacyPageInfoViewController () {
+  // Scroll View inside the PageInfoView used to display content that exceeds
+  // the available space.
+  UIScrollView* _scrollView;
+  // Container View added inside the Scroll View. All content is added to this
+  // view.
+  BidiContainerView* _innerContainerView;
+
+  // Origin of the arrow at the top of the popup window.
+  CGPoint _arrowOriginPoint;
+
+  // Model for the data to display.
+  std::unique_ptr<PageInfoModel> _model;
+
+  // Width of the view. Depends on the device (iPad/iPhone).
+  CGFloat _viewWidth;
+
+  // Width of the text fields.
+  CGFloat _textWidth;
+
+  // YES when the popup has finished animating in. NO otherwise.
+  BOOL _displayAnimationCompleted;
+}
+
+@property(nonatomic, strong) UIView* containerView;
+@property(nonatomic, strong) UIView* popupContainer;
+// An invisible button added to the |containerView|. Closes the popup just like
+// the tap on the background. Exposed purely for voiceover purposes.
+@property(nonatomic, strong) UIButton* closeButton;
+
+@end
+
+@implementation LegacyPageInfoViewController
+
+#pragma mark public
+
+- (id)initWithModel:(PageInfoModel*)model
+             sourcePoint:(CGPoint)sourcePoint
+    presentationProvider:(id<PageInfoPresentation>)provider
+                 handler:(id<BrowserCommands>)handler {
+  DCHECK(provider);
+  self = [super init];
+  if (self) {
+    _scrollView =
+        [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 240, 128)];
+    [_scrollView setMultipleTouchEnabled:YES];
+    [_scrollView setClipsToBounds:YES];
+    [_scrollView setShowsHorizontalScrollIndicator:NO];
+    [_scrollView setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
+    [_scrollView
+        setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
+                             UIViewAutoresizingFlexibleTopMargin)];
+
+    _innerContainerView =
+        [[BidiContainerView alloc] initWithFrame:CGRectMake(0, 0, 194, 327)];
+    [_innerContainerView
+        setAccessibilityLabel:@"Page Security Info Scroll Container"];
+    [_innerContainerView
+        setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
+                             UIViewAutoresizingFlexibleBottomMargin)];
+
+    _model.reset(model);
+    _arrowOriginPoint = sourcePoint;
+    _handler = handler;
+
+    UIInterfaceOrientation orientation =
+        [[UIApplication sharedApplication] statusBarOrientation];
+    _viewWidth = IsCompactWidth() ? kViewWidthCompact : kViewWidthRegular;
+    // Special case iPhone landscape.
+    if (!IsIPadIdiom() && UIInterfaceOrientationIsLandscape(orientation))
+      _viewWidth = kViewWidthiPhoneLandscape;
+
+    _textWidth = _viewWidth - (kImageSize + kImageSpacing + kFramePadding * 2 +
+                               kScrollViewInset * 2);
+
+    _containerView = [[UIView alloc] init];
+    [_containerView setBackgroundColor:[UIColor colorWithWhite:0
+                                                         alpha:kShieldAlpha]];
+    [_containerView setOpaque:NO];
+    [_containerView setAlpha:0];
+    [_containerView setAccessibilityViewIsModal:YES];
+    _containerView.accessibilityIdentifier =
+        kPageInfoViewAccessibilityIdentifier;
+
+    // Set up an invisible button that closes the popup.
+    _closeButton = [[UIButton alloc] init];
+    _closeButton.accessibilityLabel = l10n_util::GetNSString(IDS_DONE);
+    [_closeButton addTarget:handler
+                     action:@selector(hidePageInfo)
+           forControlEvents:UIControlEventTouchDown];
+    [_containerView addSubview:_closeButton];
+
+    _popupContainer = [[UIView alloc] initWithFrame:CGRectZero];
+    [_popupContainer setBackgroundColor:UIColor.cr_systemBackgroundColor];
+    [_popupContainer setClipsToBounds:YES];
+    _popupContainer.userInteractionEnabled = YES;
+    [_containerView addSubview:_popupContainer];
+
+    [self.popupContainer addSubview:_scrollView];
+    [_scrollView addSubview:_innerContainerView];
+    [_scrollView setAccessibilityIdentifier:@"Page Security Scroll View"];
+    [provider presentPageInfoView:self.containerView];
+    [self performLayout];
+
+    [self animatePageInfoViewIn:sourcePoint];
+    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+                                    _containerView);
+  }
+
+  return self;
+}
+
+- (void)performLayout {
+  CGFloat offset = kInitialLinePadding;
+
+  // Keep the new subviews in an array that gets replaced at the end.
+  NSMutableArray* subviews = [NSMutableArray array];
+
+  int sectionCount = _model->GetSectionCount();
+  PageInfoModel::ButtonAction action = PageInfoModel::BUTTON_NONE;
+
+  for (int i = 0; i < sectionCount; i++) {
+    PageInfoModel::SectionInfo info = _model->GetSectionInfo(i);
+
+    if (action == PageInfoModel::BUTTON_NONE &&
+        info.button != PageInfoModel::BUTTON_NONE) {
+      // Show the button corresponding to the first section that requires a
+      // button.
+      action = info.button;
+    }
+
+    // Only certain sections have images. This affects the X position.
+    BOOL hasImage = _model->GetIconImage(info.icon_id) != nil;
+    CGFloat xPosition = (hasImage ? kTextXPosition : kTextXPositionNoImage);
+
+    // Insert the image subview for sections that are appropriate.
+    CGFloat imageBaseline = offset + kImageSize;
+    if (hasImage) {
+      [self addImageViewForInfo:info
+                     toSubviews:subviews
+                       atOffset:offset + PageInfoImageVerticalOffset()];
+    }
+
+    // Add the title.
+    if (!info.headline.empty()) {
+      offset += [self addHeadlineViewForInfo:info
+                                  toSubviews:subviews
+                                     atPoint:CGPointMake(xPosition, offset)];
+      offset += kHeadlineSpacing;
+    }
+
+    // Create the description of the state.
+    offset += [self addDescriptionViewForInfo:info
+                                   toSubviews:subviews
+                                      atPoint:CGPointMake(xPosition, offset)];
+
+    // If at this point the description and optional headline and button are
+    // not as tall as the image, adjust the offset by the difference.
+    CGFloat imageBaselineDelta = imageBaseline - offset;
+    if (imageBaselineDelta > 0)
+      offset += imageBaselineDelta;
+
+    // Add the separators.
+    int testSectionCount = sectionCount - 1;
+    if (i != testSectionCount ||
+        (i == testSectionCount && action != PageInfoModel::BUTTON_NONE)) {
+      offset += kVerticalSpacing;
+    }
+  }
+
+  // The last item at the bottom of the window is the help center link. Do not
+  // show this for the internal pages, which have one section.
+  offset += [self addButton:action toSubviews:subviews atOffset:offset];
+
+  // Add the bottom padding.
+  offset += kVerticalSpacing;
+  CGRect frame = CGRectMake(kInitialFramePosition, _arrowOriginPoint.y,
+                            _viewWidth, offset);
+
+  // Increase the size of the frame by the amount used for drawing rounded
+  // corners and shadow.
+  frame.size.height += kPageInfoViewFooterSize;
+
+  if (CGRectGetMaxY(frame) >
+      CGRectGetMaxY([[self containerView] superview].bounds) -
+          kFrameBottomPadding) {
+    // If the frame is bigger than the parent view than change the frame to
+    // fit in the superview bounds.
+    frame.size.height = [[self containerView] superview].bounds.size.height -
+                        kFrameBottomPadding - frame.origin.y;
+
+    [_scrollView setScrollEnabled:YES];
+    [_scrollView flashScrollIndicators];
+  } else {
+    [_scrollView setScrollEnabled:NO];
+  }
+
+  CGRect containerBounds = [_containerView bounds];
+  CGRect popupFrame = frame;
+  popupFrame.origin.x =
+      CGRectGetMidX(containerBounds) - CGRectGetWidth(popupFrame) / 2.0;
+  popupFrame.origin.y =
+      CGRectGetMidY(containerBounds) - CGRectGetHeight(popupFrame) / 2.0;
+
+  popupFrame.origin = AlignPointToPixel(popupFrame.origin);
+  CGRect innerFrame = CGRectMake(0, 0, popupFrame.size.width, offset);
+
+  // If the initial animation has completed, animate the new frames.
+  if (_displayAnimationCompleted) {
+    [UIView cr_animateWithDuration:ios::material::kDuration3
+                             delay:0
+                             curve:ios::material::CurveEaseInOut
+                           options:0
+                        animations:^{
+                          [_popupContainer setFrame:popupFrame];
+                          [_scrollView setFrame:[_popupContainer bounds]];
+                          [_innerContainerView setFrame:innerFrame];
+                        }
+                        completion:nil];
+  } else {
+    // Popup hasn't finished animating in yet. Set frames immediately.
+    [_popupContainer setFrame:popupFrame];
+    [_scrollView setFrame:[_popupContainer bounds]];
+    [_innerContainerView setFrame:innerFrame];
+  }
+
+  for (UIView* view in [_innerContainerView subviews]) {
+    [view removeFromSuperview];
+  }
+
+  for (UIView* view in subviews) {
+    [_innerContainerView addSubview:view];
+    [_innerContainerView setSubviewNeedsAdjustmentForRTL:view];
+  }
+
+  [_scrollView setContentSize:_innerContainerView.frame.size];
+  _closeButton.frame = _containerView.bounds;
+}
+
+- (void)dismiss {
+  [self animatePageInfoViewOut];
+  UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+                                  nil);
+}
+
+#pragma mark - internal
+
+- (BOOL)accessibilityPerformEscape {
+  [self.handler hidePageInfo];
+  return YES;
+}
+
+- (void)animatePageInfoViewIn:(CGPoint)sourcePoint {
+  // Animate the info card itself.
+  CATransform3D scaleTransform = PageInfoAnimationScale();
+
+  CABasicAnimation* scaleAnimation =
+      [CABasicAnimation animationWithKeyPath:@"transform"];
+  [scaleAnimation setFromValue:[NSValue valueWithCATransform3D:scaleTransform]];
+
+  CABasicAnimation* positionAnimation =
+      [CABasicAnimation animationWithKeyPath:@"position"];
+  [positionAnimation setFromValue:[NSValue valueWithCGPoint:sourcePoint]];
+
+  CAAnimationGroup* sizeAnimation = [CAAnimationGroup animation];
+  [sizeAnimation setAnimations:@[ scaleAnimation, positionAnimation ]];
+  [sizeAnimation
+      setTimingFunction:TimingFunction(ios::material::CurveEaseInOut)];
+  [sizeAnimation setDuration:ios::material::kDuration3];
+
+  CABasicAnimation* fadeAnimation =
+      [CABasicAnimation animationWithKeyPath:@"opacity"];
+  [fadeAnimation setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+  [fadeAnimation setDuration:ios::material::kDuration6];
+  [fadeAnimation setFromValue:@0];
+  [fadeAnimation setToValue:@1];
+
+  [[_popupContainer layer] addAnimation:fadeAnimation forKey:@"fade"];
+  [[_popupContainer layer] addAnimation:sizeAnimation forKey:@"size"];
+
+  // Animation the background grey overlay.
+  CABasicAnimation* overlayAnimation =
+      [CABasicAnimation animationWithKeyPath:@"opacity"];
+  [overlayAnimation
+      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+  [overlayAnimation setDuration:ios::material::kDuration3];
+  [overlayAnimation setFromValue:@0];
+  [overlayAnimation setToValue:@1];
+
+  [[_containerView layer] addAnimation:overlayAnimation forKey:@"fade"];
+  [_containerView setAlpha:1];
+
+  // Animate the contents of the info card.
+  CALayer* contentsLayer = [_innerContainerView layer];
+
+  CGRect startFrame = CGRectOffset([_innerContainerView frame], 0, -32);
+  CAAnimation* contentSlideAnimation = FrameAnimationMake(
+      contentsLayer, startFrame, [_innerContainerView frame]);
+  [contentSlideAnimation
+      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+  [contentSlideAnimation setDuration:ios::material::kDuration5];
+  contentSlideAnimation =
+      DelayedAnimationMake(contentSlideAnimation, ios::material::kDuration2);
+  [contentsLayer addAnimation:contentSlideAnimation forKey:@"slide"];
+
+  [CATransaction begin];
+  [CATransaction setCompletionBlock:^{
+    [_innerContainerView setAlpha:1];
+    _displayAnimationCompleted = YES;
+  }];
+  CAAnimation* contentFadeAnimation = OpacityAnimationMake(0.0, 1.0);
+  [contentFadeAnimation
+      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
+  [contentFadeAnimation setDuration:ios::material::kDuration5];
+  contentFadeAnimation =
+      DelayedAnimationMake(contentFadeAnimation, ios::material::kDuration1);
+  [contentsLayer addAnimation:contentFadeAnimation forKey:@"fade"];
+  [CATransaction commit];
+
+  // Since the animations have delay on them, the alpha of the content view
+  // needs to be set to zero and then one after the animation starts. If these
+  // steps are not taken, there will be a visible flash/jump from the initial
+  // spot during the animation.
+  [_innerContainerView setAlpha:0];
+}
+
+- (void)animatePageInfoViewOut {
+  [CATransaction begin];
+  [CATransaction setCompletionBlock:^{
+    [self.containerView removeFromSuperview];
+  }];
+
+  CABasicAnimation* opacityAnimation =
+      [CABasicAnimation animationWithKeyPath:@"opacity"];
+  [opacityAnimation
+      setTimingFunction:TimingFunction(ios::material::CurveEaseIn)];
+  [opacityAnimation setDuration:ios::material::kDuration3];
+  [opacityAnimation setFromValue:@1];
+  [opacityAnimation setToValue:@0];
+  [[_containerView layer] addAnimation:opacityAnimation forKey:@"animateOut"];
+
+  [_popupContainer setAlpha:0];
+  [_containerView setAlpha:0];
+  [CATransaction commit];
+}
+
+#pragma mark - Helper methods to create subviews.
+
+// Adds the state image at a pre-determined x position and the given y. This
+// does not affect the next Y position because the image is placed next to
+// a text field that is larger and accounts for the image's size.
+- (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
+                 toSubviews:(NSMutableArray*)subviews
+                   atOffset:(CGFloat)offset {
+  CGRect frame = CGRectMake(kFramePadding, offset, kImageSize, kImageSize);
+  UIImageView* imageView = [[UIImageView alloc] initWithFrame:frame];
+  imageView.tintColor = UIColor.cr_labelColor;
+  UIImage* image = [_model->GetIconImage(info.icon_id)->ToUIImage()
+      imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  [imageView setImage:image];
+  [subviews addObject:imageView];
+}
+
+// Adds the title text field at the given x,y position, and returns the y
+// position for the next element.
+- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
+                       toSubviews:(NSMutableArray*)subviews
+                          atPoint:(CGPoint)point {
+  CGRect frame = CGRectMake(point.x, point.y, _textWidth, kHeadlineHeight);
+  UILabel* label = [[UILabel alloc] initWithFrame:frame];
+  [label setTextAlignment:NSTextAlignmentNatural];
+  [label setText:base::SysUTF16ToNSString(info.headline)];
+  [label setTextColor:UIColor.cr_labelColor];
+  [label setFont:PageInfoHeadlineFont()];
+  [label setFrame:frame];
+  [label setLineBreakMode:NSLineBreakByTruncatingHead];
+  [subviews addObject:label];
+  return CGRectGetHeight(frame);
+}
+
+// Adds the description text field at the given x,y position, and returns the y
+// position for the next element.
+- (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
+                          toSubviews:(NSMutableArray*)subviews
+                             atPoint:(CGPoint)point {
+  CGRect frame = CGRectMake(point.x, point.y, _textWidth, kImageSize);
+  UILabel* label = [[UILabel alloc] initWithFrame:frame];
+  [label setTextAlignment:NSTextAlignmentNatural];
+  NSString* description = base::SysUTF16ToNSString(info.description);
+  UIFont* font = [MDCTypography captionFont];
+  [label setTextColor:UIColor.cr_labelColor];
+  [label setText:description];
+  [label setFont:font];
+  [label setNumberOfLines:0];
+
+  // If the text is oversized, resize the text field.
+  CGSize constraintSize = CGSizeMake(_textWidth, CGFLOAT_MAX);
+  CGSize sizeToFit = [description cr_boundingSizeWithSize:constraintSize
+                                                     font:font];
+  frame.size.height = sizeToFit.height;
+  [label setFrame:frame];
+  [subviews addObject:label];
+  return CGRectGetHeight(frame);
+}
+
+// Returns a button with title and action configured for |buttonAction|.
+- (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction {
+  if (buttonAction == PageInfoModel::BUTTON_NONE) {
+    return nil;
+  }
+  UIButton* button = [[UIButton alloc] initWithFrame:CGRectZero];
+  int messageId;
+  NSString* accessibilityID = @"Reload button";
+  switch (buttonAction) {
+    case PageInfoModel::BUTTON_NONE:
+      NOTREACHED();
+      return nil;
+    case PageInfoModel::BUTTON_SHOW_SECURITY_HELP:
+      messageId = IDS_LEARN_MORE;
+      accessibilityID = @"Learn more";
+      [button addTarget:self.handler
+                    action:@selector(showSecurityHelpPage)
+          forControlEvents:UIControlEventTouchUpInside];
+      break;
+    case PageInfoModel::BUTTON_RELOAD:
+      messageId = IDS_IOS_PAGE_INFO_RELOAD;
+      accessibilityID = @"Reload button";
+      [button addTarget:self.handler
+                    action:@selector(hidePageInfo)
+          forControlEvents:UIControlEventTouchUpInside];
+      [button addTarget:self.handler
+                    action:@selector(reload)
+          forControlEvents:UIControlEventTouchUpInside];
+      break;
+  };
+
+  NSString* title = l10n_util::GetNSStringWithFixup(messageId);
+  SetA11yLabelAndUiAutomationName(button, messageId, accessibilityID);
+  [button setTitle:title forState:UIControlStateNormal];
+  return button;
+}
+
+// Adds the the button |buttonAction| that explains the icons. Returns the y
+// position delta for the next offset.
+- (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
+          toSubviews:(NSMutableArray*)subviews
+            atOffset:(CGFloat)offset {
+  UIButton* button = [self buttonForAction:buttonAction];
+  if (!button) {
+    return 0;
+  }
+  // The size of the initial frame is irrelevant since it will be changed based
+  // on the size for the string inside.
+  CGRect frame = CGRectMake(kButtonXOffset, offset, 100, 10);
+
+  UIFont* font = [MDCTypography captionFont];
+  CGSize sizeWithFont =
+      [[[button titleLabel] text] cr_pixelAlignedSizeWithFont:font];
+  frame.size = sizeWithFont;
+  // According to iOS Human Interface Guidelines, minimal size of UIButton
+  // should be 44x44.
+  frame.size.height = std::max<CGFloat>(44, frame.size.height);
+
+  [button setFrame:frame];
+
+  [button.titleLabel setFont:font];
+  [button.titleLabel setTextAlignment:NSTextAlignmentLeft];
+  [button setTitleColor:[UIColor colorNamed:kBlueColor]
+               forState:UIControlStateNormal];
+  [button setTitleColor:[UIColor colorNamed:kBlueColor]
+               forState:UIControlStateSelected];
+
+  [subviews addObject:button];
+
+  return CGRectGetHeight([button frame]);
+}
+
+@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_constants.h b/ios/chrome/browser/ui/page_info/page_info_constants.h
index ce16866..5ae19ab 100644
--- a/ios/chrome/browser/ui/page_info/page_info_constants.h
+++ b/ios/chrome/browser/ui/page_info/page_info_constants.h
@@ -10,4 +10,9 @@
 // Accessibility identifier for the page info view.
 extern NSString* const kPageInfoViewAccessibilityIdentifier;
 
+// Notification sent when the page info is shown.
+extern NSString* const kPageInfoWillShowNotification;
+// Notification sent when the page info is hidden.
+extern NSString* const kPageInfoWillHideNotification;
+
 #endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_constants.mm b/ios/chrome/browser/ui/page_info/page_info_constants.mm
index 101acfe2..7f41e4ed 100644
--- a/ios/chrome/browser/ui/page_info/page_info_constants.mm
+++ b/ios/chrome/browser/ui/page_info/page_info_constants.mm
@@ -10,3 +10,9 @@
 
 NSString* const kPageInfoViewAccessibilityIdentifier =
     @"PageInfoViewAccessibilityIdentifier";
+
+NSString* const kPageInfoWillShowNotification =
+    @"kPageInfoWillShowNotification";
+
+NSString* const kPageInfoWillHideNotification =
+    @"kPageInfoWillHideNotification";
diff --git a/ios/chrome/browser/ui/page_info/page_info_coordinator.h b/ios/chrome/browser/ui/page_info/page_info_coordinator.h
new file mode 100644
index 0000000..8b83469
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/page_info_coordinator.h
@@ -0,0 +1,23 @@
+// 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_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COORDINATOR_H_
+
+#import <Foundation/Foundation.h>
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+@protocol PageInfoPresentation;
+
+// The coordinator for the page info.
+@interface PageInfoCoordinator : ChromeCoordinator
+
+// |presentationProvider| provides information and runs tasks necessary to
+// present Page Info.
+@property(nonatomic, weak) id<PageInfoPresentation> presentationProvider;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_coordinator.mm b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm
new file mode 100644
index 0000000..1e5c7c1
--- /dev/null
+++ b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm
@@ -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.
+
+#import "ios/chrome/browser/ui/page_info/page_info_coordinator.h"
+
+#include "base/logging.h"
+#include "ios/chrome/browser/main/browser.h"
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/page_info/page_info_view_controller.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface PageInfoCoordinator ()
+
+@end
+
+@implementation PageInfoCoordinator
+
+@synthesize presentationProvider = _presentationProvider;
+
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  // TODO(crbug.com/1038919): Implement this.
+}
+
+- (void)stop {
+  // TODO(crbug.com/1038919): Implement this.
+}
+
+@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h
index 64cc28f..0d2c29e 100644
--- a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h
+++ b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h
@@ -9,11 +9,6 @@
 
 @protocol PageInfoPresentation;
 
-// Notification sent when the page info is shown.
-extern NSString* const kPageInfoWillShowNotification;
-// Notification sent when the page info is hidden.
-extern NSString* const kPageInfoWillHideNotification;
-
 // The coordinator that manages the display of the Page Info UI. When
 // |dispatcher| is set, this coordinator uses |dispatcher| to register itself
 // as the target for PageInfoCommmands. These commands can then trigger the
@@ -27,6 +22,10 @@
                                   (ios::ChromeBrowserState*)browserState
     NS_UNAVAILABLE;
 
+//|originPoint| is the midpoint of the UI element from which the page info
+// should start presenting.
+@property(nonatomic, assign) CGPoint originPoint;
+
 // |presentationProvider| provides information and runs tasks necessary to
 // present Page Info.
 @property(nonatomic, weak) id<PageInfoPresentation> presentationProvider;
diff --git a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm
index 6137b4c2..c822d6a 100644
--- a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm
+++ b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm
@@ -13,14 +13,14 @@
 #import "ios/chrome/browser/main/browser.h"
 #import "ios/chrome/browser/reading_list/offline_page_tab_helper.h"
 #include "ios/chrome/browser/reading_list/offline_url_utils.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-#import "ios/chrome/browser/ui/commands/page_info_commands.h"
 #import "ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.h"
+#import "ios/chrome/browser/ui/page_info/legacy_page_info_view_controller.h"
+#import "ios/chrome/browser/ui/page_info/page_info_constants.h"
 #include "ios/chrome/browser/ui/page_info/page_info_model.h"
-#import "ios/chrome/browser/ui/page_info/page_info_view_controller.h"
 #import "ios/chrome/browser/ui/page_info/requirements/page_info_presentation.h"
-#import "ios/chrome/browser/ui/page_info/requirements/page_info_reloading.h"
 #import "ios/chrome/browser/url_loading/url_loading_params.h"
 #import "ios/chrome/browser/url_loading/url_loading_service.h"
 #import "ios/chrome/browser/url_loading/url_loading_service_factory.h"
@@ -35,40 +35,21 @@
 #error "This file requires ARC support."
 #endif
 
-NSString* const kPageInfoWillShowNotification =
-    @"kPageInfoWillShowNotification";
-
-NSString* const kPageInfoWillHideNotification =
-    @"kPageInfoWillHideNotification";
-
-@interface PageInfoLegacyCoordinator ()<PageInfoCommands, PageInfoReloading>
+@interface PageInfoLegacyCoordinator ()
 
 // The view controller for the Page Info UI. Nil if not visible.
-@property(nonatomic, strong) PageInfoViewController* pageInfoViewController;
+@property(nonatomic, strong)
+    LegacyPageInfoViewController* pageInfoViewController;
 
 @end
 
 @implementation PageInfoLegacyCoordinator
 
+@synthesize presentationProvider = _presentationProvider;
+
 #pragma mark - ChromeCoordinator
 
 - (void)start {
-  [self.browser->GetCommandDispatcher()
-      startDispatchingToTarget:self
-                   forProtocol:@protocol(PageInfoCommands)];
-}
-
-- (void)stop {
-  [super stop];
-  // DCHECK that the Page Info UI is not displayed before disconnecting.
-  DCHECK(!self.pageInfoViewController);
-  [self.browser->GetCommandDispatcher() stopDispatchingToTarget:self];
-  self.presentationProvider = nil;
-}
-
-#pragma mark - PageInfoCommands
-
-- (void)showPageInfoForOriginPoint:(CGPoint)originPoint {
   web::WebState* webState =
       self.browser->GetWebStateList()->GetActiveWebState();
   web::NavigationItem* navItem =
@@ -103,23 +84,21 @@
       OfflinePageTabHelper::FromWebState(webState)->presenting_offline_page();
 
   // TODO(crbug.com/760387): Get rid of PageInfoModel completely.
-  PageInfoModelBubbleBridge* bridge = new PageInfoModelBubbleBridge();
-  PageInfoModel* pageInfoModel =
-      new PageInfoModel(self.browserState, navItem->GetURL(), navItem->GetSSL(),
-                        presenting_offline_page, bridge);
+  PageInfoModel* pageInfoModel = new PageInfoModel(
+      navItem->GetURL(), navItem->GetSSL(), presenting_offline_page);
 
   CGPoint originPresentationCoordinates = [self.presentationProvider
-      convertToPresentationCoordinatesForOrigin:originPoint];
-  self.pageInfoViewController = [[PageInfoViewController alloc]
+      convertToPresentationCoordinatesForOrigin:self.originPoint];
+  self.pageInfoViewController = [[LegacyPageInfoViewController alloc]
              initWithModel:pageInfoModel
-                    bridge:bridge
                sourcePoint:originPresentationCoordinates
       presentationProvider:self.presentationProvider
-                dispatcher:self];
-  bridge->set_controller(self.pageInfoViewController);
+                   handler:HandlerForProtocol(
+                               self.browser->GetCommandDispatcher(),
+                               BrowserCommands)];
 }
 
-- (void)hidePageInfo {
+- (void)stop {
   // Early return if the PageInfoPopup is not presented.
   if (!self.pageInfoViewController)
     return;
@@ -135,24 +114,4 @@
   self.pageInfoViewController = nil;
 }
 
-- (void)showSecurityHelpPage {
-  UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kPageInfoHelpCenterURL));
-  params.in_incognito = self.browserState->IsOffTheRecord();
-  UrlLoadingServiceFactory::GetForBrowserState(self.browserState)->Load(params);
-  [self hidePageInfo];
-}
-
-#pragma mark - PageInfoReloading
-
-- (void)reload {
-  web::WebState* webState =
-      self.browser->GetWebStateList()->GetActiveWebState();
-  if (webState) {
-    // |check_for_repost| is true because the reload is explicitly initiated
-    // by the user.
-    webState->GetNavigationManager()->Reload(web::ReloadType::NORMAL,
-                                             true /* check_for_repost */);
-  }
-}
-
 @end
diff --git a/ios/chrome/browser/ui/page_info/page_info_model.cc b/ios/chrome/browser/ui/page_info/page_info_model.cc
index 5cff2621..9505470 100644
--- a/ios/chrome/browser/ui/page_info/page_info_model.cc
+++ b/ios/chrome/browser/ui/page_info/page_info_model.cc
@@ -21,9 +21,7 @@
 #include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_google_chrome_strings.h"
 #include "components/strings/grit/components_strings.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/ui/page_info/page_info_model_observer.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
@@ -37,28 +35,24 @@
 
 // TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in
 // upstream; check if we should use PageInfoModel.
-PageInfoModel::PageInfoModel(ios::ChromeBrowserState* browser_state,
-                             const GURL& url,
+PageInfoModel::PageInfoModel(const GURL& url,
                              const web::SSLStatus& ssl,
-                             bool is_offline_page,
-                             PageInfoModelObserver* observer)
-    : observer_(observer) {
+                             bool is_offline_page) {
   if (is_offline_page) {
     sections_.push_back(
         SectionInfo(ICON_STATE_OFFLINE_PAGE,
                     l10n_util::GetStringUTF16(IDS_IOS_PAGE_INFO_OFFLINE_TITLE),
                     l10n_util::GetStringUTF16(IDS_IOS_PAGE_INFO_OFFLINE_PAGE),
-                    SECTION_INFO_INTERNAL_PAGE, BUTTON_RELOAD));
+                    BUTTON_RELOAD));
     return;
   }
 
   if (url.SchemeIs(kChromeUIScheme)) {
     base::string16 spec(base::UTF8ToUTF16(url.spec()));
 
-    sections_.push_back(
-        SectionInfo(ICON_STATE_INTERNAL_PAGE, spec,
-                    l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE),
-                    SECTION_INFO_INTERNAL_PAGE, BUTTON_NONE));
+    sections_.push_back(SectionInfo(
+        ICON_STATE_INTERNAL_PAGE, spec,
+        l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE), BUTTON_NONE));
     return;
   }
 
@@ -157,7 +151,6 @@
   }
 
   sections_.push_back(SectionInfo(icon_id, hostname, description,
-                                  SECTION_INFO_CONNECTION,
                                   BUTTON_SHOW_SECURITY_HELP));
 }
 
@@ -188,9 +181,3 @@
       return &rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_OFFLINE);
   }
 }
-
-base::string16 PageInfoModel::GetCertificateLabel() const {
-  return certificate_label_;
-}
-
-PageInfoModel::PageInfoModel() : observer_(NULL) {}
diff --git a/ios/chrome/browser/ui/page_info/page_info_model.h b/ios/chrome/browser/ui/page_info/page_info_model.h
index ae062b6..89f07fd2 100644
--- a/ios/chrome/browser/ui/page_info/page_info_model.h
+++ b/ios/chrome/browser/ui/page_info/page_info_model.h
@@ -11,12 +11,6 @@
 #include "ui/gfx/image/image.h"
 #include "url/gurl.h"
 
-class PageInfoModelObserver;
-
-namespace ios {
-class ChromeBrowserState;
-}
-
 namespace web {
 struct SSLStatus;
 }
@@ -27,13 +21,6 @@
 // info dialog/bubble.
 class PageInfoModel {
  public:
-  enum SectionInfoType {
-    SECTION_INFO_IDENTITY = 0,
-    SECTION_INFO_CONNECTION,
-    SECTION_INFO_FIRST_VISIT,
-    SECTION_INFO_INTERNAL_PAGE,  // Used for chrome:// pages, etc.
-  };
-
   // NOTE: ICON_STATE_OK ... ICON_STATE_ERROR must be listed in increasing
   // order of severity.  Code may depend on this order.
   enum SectionStateIcon {
@@ -66,12 +53,10 @@
     SectionInfo(SectionStateIcon icon_id,
                 const base::string16& headline,
                 const base::string16& description,
-                SectionInfoType type,
                 ButtonAction button)
         : icon_id(icon_id),
           headline(headline),
           description(description),
-          type(type),
           button(button) {}
 
     // The overall state of the connection (error, warning, ok).
@@ -83,21 +68,15 @@
     // The full description of what this section is.
     base::string16 description;
 
-    // The type of SectionInfo we are dealing with, for example: Identity,
-    // Connection, First Visit.
-    SectionInfoType type;
-
     // The button at the bottom of the sheet that allows the user to do an extra
     // action on top of dismissing the sheet.
     ButtonAction button;
   };
   // |is_offline_page| is true if related WebState presents Offline Version of
   // the page.
-  PageInfoModel(ios::ChromeBrowserState* browser_state,
-                const GURL& url,
+  PageInfoModel(const GURL& url,
                 const web::SSLStatus& ssl,
-                bool is_offline_page,
-                PageInfoModelObserver* observer);
+                bool is_offline_page);
   ~PageInfoModel();
 
   int GetSectionCount();
@@ -106,20 +85,9 @@
   // Returns the native image type for an icon with the given id.
   gfx::Image* GetIconImage(SectionStateIcon icon_id);
 
-  // Returns the label for the "Certificate Information", if needed.
-  base::string16 GetCertificateLabel() const;
-
  protected:
-  // Testing constructor. DO NOT USE.
-  PageInfoModel();
-
-  PageInfoModelObserver* observer_;
-
   std::vector<SectionInfo> sections_;
 
-  // Label for "Certificate Information", if needed.
-  base::string16 certificate_label_;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(PageInfoModel);
 };
diff --git a/ios/chrome/browser/ui/page_info/page_info_model_observer.h b/ios/chrome/browser/ui/page_info/page_info_model_observer.h
deleted file mode 100644
index 139971c..0000000
--- a/ios/chrome/browser/ui/page_info/page_info_model_observer.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MODEL_OBSERVER_H_
-#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MODEL_OBSERVER_H_
-
-// TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in
-// upstream; check if we should use PageInfoModel.
-// This interface should be implemented by classes interested in getting
-// notifications from PageInfoModel.
-class PageInfoModelObserver {
- public:
-  virtual ~PageInfoModelObserver() {}
-
-  virtual void OnPageInfoModelChanged() = 0;
-};
-
-#endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MODEL_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.h b/ios/chrome/browser/ui/page_info/page_info_view_controller.h
index b757e53..867ab66a 100644
--- a/ios/chrome/browser/ui/page_info/page_info_view_controller.h
+++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 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.
 
@@ -7,64 +7,9 @@
 
 #import <UIKit/UIKit.h>
 
-#include <memory>
-
-#include "base/memory/weak_ptr.h"
-#include "ios/chrome/browser/ui/page_info/page_info_model_observer.h"
-
-@class BidiContainerView;
-@protocol PageInfoCommands;
-@protocol PageInfoPresentation;
-@protocol PageInfoReloading;
-class PageInfoModel;
-
-// TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in
-// upstream; check if we should use PageInfoModel.
-// The view controller for the page info view.
-@interface PageInfoViewController : NSObject
-// Designated initializer.
-// The |sourcePoint| parameter should be in the coordinate system of
-// |provider|'s view. Typically, |sourcePoint| would be the midpoint of a button
-// that resulted in this popup being displayed.
-- (id)initWithModel:(PageInfoModel*)model
-                  bridge:(PageInfoModelObserver*)bridge
-             sourcePoint:(CGPoint)sourcePoint
-    presentationProvider:(id<PageInfoPresentation>)provider
-              dispatcher:(id<PageInfoCommands, PageInfoReloading>)dispatcher;
-
-// Dispatcher for this view controller.
-@property(nonatomic, weak) id<PageInfoCommands, PageInfoReloading> dispatcher;
-
-// Dismisses the view.
-- (void)dismiss;
-
-// Layout the page info view.
-- (void)performLayout;
+// View Controller for displaying the page info.
+@interface PageInfoViewController : UIViewController
 
 @end
 
-// Bridge that listens for change notifications from the model.
-class PageInfoModelBubbleBridge : public PageInfoModelObserver {
- public:
-  PageInfoModelBubbleBridge();
-  ~PageInfoModelBubbleBridge() override;
-
-  // PageInfoModelObserver implementation.
-  void OnPageInfoModelChanged() override;
-
-  // Sets the controller.
-  void set_controller(PageInfoViewController* controller) {
-    controller_ = controller;
-  }
-
- private:
-  void PerformLayout();
-
-  __weak PageInfoViewController* controller_ = nil;
-
-  base::WeakPtrFactory<PageInfoModelBubbleBridge> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PageInfoModelBubbleBridge);
-};
-
 #endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
index 049cbf6..67023f9e 100644
--- a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
+++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
@@ -1,615 +1,13 @@
-// Copyright (c) 2012 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.
 
 #import "ios/chrome/browser/ui/page_info/page_info_view_controller.h"
 
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/mac/bundle_locations.h"
-#import "base/mac/foundation_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/strings/grit/components_strings.h"
-#import "ios/chrome/browser/ui/commands/page_info_commands.h"
-#import "ios/chrome/browser/ui/fancy_ui/bidi_container_view.h"
-#import "ios/chrome/browser/ui/page_info/page_info_constants.h"
-#include "ios/chrome/browser/ui/page_info/page_info_model.h"
-#import "ios/chrome/browser/ui/page_info/requirements/page_info_presentation.h"
-#import "ios/chrome/browser/ui/page_info/requirements/page_info_reloading.h"
-#import "ios/chrome/browser/ui/util/animation_util.h"
-#include "ios/chrome/browser/ui/util/rtl_geometry.h"
-#include "ios/chrome/browser/ui/util/ui_util.h"
-#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
-#import "ios/chrome/common/colors/UIColor+cr_semantic_colors.h"
-#import "ios/chrome/common/colors/semantic_color_names.h"
-#import "ios/chrome/common/material_timing.h"
-#include "ios/chrome/grit/ios_strings.h"
-#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/l10n_util_mac.h"
-#import "ui/gfx/ios/NSString+CrStringDrawing.h"
-#import "ui/gfx/ios/uikit_util.h"
-
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-using ios::material::TimingFunction;
-
-namespace {
-
-// The width of the view.
-const CGFloat kViewWidthRegular = 600.0;
-const CGFloat kViewWidthCompact = 288.0;
-const CGFloat kViewWidthiPhoneLandscape = 400.0;
-// Spacing in between sections.
-const CGFloat kVerticalSpacing = 20.0;
-// Initial position for the left side of the frame.
-const CGFloat kInitialFramePosition = 8.0;
-// Alpha for the shield.
-const CGFloat kShieldAlpha = 0.5;
-// Scroll View inset.
-const CGFloat kScrollViewInset = 5.0;
-// The size of the footer (rounded corner and shadow) for page info view.
-const CGFloat kPageInfoViewFooterSize = 15.0;
-// Padding between the window frame and content.
-const CGFloat kFramePadding = 24;
-// Padding for the initial line of the view.
-const CGFloat kInitialLinePadding = 40;
-// Padding between the bottom of the content and the window frame.
-const CGFloat kFrameBottomPadding = 16;
-// Spacing between the optional headline and description text views.
-const CGFloat kHeadlineSpacing = 16;
-// Spacing between the image and the text.
-const CGFloat kImageSpacing = 16;
-// Square size of the image.
-const CGFloat kImageSize = 24;
-// The height of the headline label.
-const CGFloat kHeadlineHeight = 19;
-
-inline UIFont* PageInfoHeadlineFont() {
-  return [[MDCTypography fontLoader] mediumFontOfSize:16];
-}
-
-inline CATransform3D PageInfoAnimationScale() {
-  return CATransform3DMakeScale(0.03, 0.03, 1);
-}
-
-// Offset to make sure image aligns with the header line.
-inline CGFloat PageInfoImageVerticalOffset() {
-  return ui::AlignValueToUpperPixel((kHeadlineHeight - kImageSize) / 2.0);
-}
-
-// The X position of the text fields. Variants for with and without an image.
-const CGFloat kTextXPositionNoImage = kFramePadding;
-const CGFloat kTextXPosition =
-    kTextXPositionNoImage + kImageSize + kImageSpacing;
-
-// The X offset for the help button.
-const CGFloat kButtonXOffset = kTextXPosition;
-
-}  // namespace
-
-#pragma mark - PageInfoModelBubbleBridge
-
-PageInfoModelBubbleBridge::PageInfoModelBubbleBridge()
-    : controller_(nil), weak_ptr_factory_(this) {}
-
-PageInfoModelBubbleBridge::~PageInfoModelBubbleBridge() {}
-
-void PageInfoModelBubbleBridge::OnPageInfoModelChanged() {
-  // Check to see if a layout has already been scheduled.
-  if (weak_ptr_factory_.HasWeakPtrs())
-    return;
-
-  // Delay performing layout by a second so that all the animations from
-  // InfoBubbleWindow and origin updates from BaseBubbleController finish, so
-  // that we don't all race trying to change the frame's origin.
-  //
-  // Using MessageLoop is superior here to |-performSelector:| because it will
-  // not retain its target; if the child outlives its parent, zombies get left
-  // behind (http://crbug.com/59619). This will cancel the scheduled task if
-  // the controller (and thus this bridge) get destroyed before the message
-  // can be delivered.
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&PageInfoModelBubbleBridge::PerformLayout,
-                     weak_ptr_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMilliseconds(1000 /* milliseconds */));
-}
-
-void PageInfoModelBubbleBridge::PerformLayout() {
-  // If the window is animating closed when this is called, the
-  // animation could be holding the last reference to |controller_|
-  // (and thus |this|).  Pin it until the task is completed.
-  NS_VALID_UNTIL_END_OF_SCOPE PageInfoViewController* keep_alive = controller_;
-  [controller_ performLayout];
-}
-
-#pragma mark - PageInfoViewController
-
-@interface PageInfoViewController () {
-  // Scroll View inside the PageInfoView used to display content that exceeds
-  // the available space.
-  UIScrollView* _scrollView;
-  // Container View added inside the Scroll View. All content is added to this
-  // view.
-  BidiContainerView* _innerContainerView;
-
-  // Origin of the arrow at the top of the popup window.
-  CGPoint _arrowOriginPoint;
-
-  // Model for the data to display.
-  std::unique_ptr<PageInfoModel> _model;
-
-  // Thin bridge that pushes model-changed notifications from C++ to Cocoa.
-  std::unique_ptr<PageInfoModelObserver> _modelBridge;
-
-  // Width of the view. Depends on the device (iPad/iPhone).
-  CGFloat _viewWidth;
-
-  // Width of the text fields.
-  CGFloat _textWidth;
-
-  // YES when the popup has finished animating in. NO otherwise.
-  BOOL _displayAnimationCompleted;
-}
-
-@property(nonatomic, strong) UIView* containerView;
-@property(nonatomic, strong) UIView* popupContainer;
-// An invisible button added to the |containerView|. Closes the popup just like
-// the tap on the background. Exposed purely for voiceover purposes.
-@property(nonatomic, strong) UIButton* closeButton;
-
-@end
-
 @implementation PageInfoViewController
 
-#pragma mark public
-
-- (id)initWithModel:(PageInfoModel*)model
-                  bridge:(PageInfoModelObserver*)bridge
-             sourcePoint:(CGPoint)sourcePoint
-    presentationProvider:(id<PageInfoPresentation>)provider
-              dispatcher:(id<PageInfoCommands, PageInfoReloading>)dispatcher {
-  DCHECK(provider);
-  self = [super init];
-  if (self) {
-    _scrollView =
-        [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 240, 128)];
-    [_scrollView setMultipleTouchEnabled:YES];
-    [_scrollView setClipsToBounds:YES];
-    [_scrollView setShowsHorizontalScrollIndicator:NO];
-    [_scrollView setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
-    [_scrollView
-        setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
-                             UIViewAutoresizingFlexibleTopMargin)];
-
-    _innerContainerView =
-        [[BidiContainerView alloc] initWithFrame:CGRectMake(0, 0, 194, 327)];
-    [_innerContainerView
-        setAccessibilityLabel:@"Page Security Info Scroll Container"];
-    [_innerContainerView
-        setAutoresizingMask:(UIViewAutoresizingFlexibleTrailingMargin() |
-                             UIViewAutoresizingFlexibleBottomMargin)];
-
-    _model.reset(model);
-    _modelBridge.reset(bridge);
-    _arrowOriginPoint = sourcePoint;
-    _dispatcher = dispatcher;
-
-    UIInterfaceOrientation orientation =
-        [[UIApplication sharedApplication] statusBarOrientation];
-    _viewWidth = IsCompactWidth() ? kViewWidthCompact : kViewWidthRegular;
-    // Special case iPhone landscape.
-    if (!IsIPadIdiom() && UIInterfaceOrientationIsLandscape(orientation))
-      _viewWidth = kViewWidthiPhoneLandscape;
-
-    _textWidth = _viewWidth - (kImageSize + kImageSpacing + kFramePadding * 2 +
-                               kScrollViewInset * 2);
-
-    _containerView = [[UIView alloc] init];
-    [_containerView setBackgroundColor:[UIColor colorWithWhite:0
-                                                         alpha:kShieldAlpha]];
-    [_containerView setOpaque:NO];
-    [_containerView setAlpha:0];
-    [_containerView setAccessibilityViewIsModal:YES];
-    _containerView.accessibilityIdentifier =
-        kPageInfoViewAccessibilityIdentifier;
-
-    // Set up an invisible button that closes the popup.
-    _closeButton = [[UIButton alloc] init];
-    _closeButton.accessibilityLabel = l10n_util::GetNSString(IDS_DONE);
-    [_closeButton addTarget:dispatcher
-                     action:@selector(hidePageInfo)
-           forControlEvents:UIControlEventTouchDown];
-    [_containerView addSubview:_closeButton];
-
-    _popupContainer = [[UIView alloc] initWithFrame:CGRectZero];
-    [_popupContainer setBackgroundColor:UIColor.cr_systemBackgroundColor];
-    [_popupContainer setClipsToBounds:YES];
-    _popupContainer.userInteractionEnabled = YES;
-    [_containerView addSubview:_popupContainer];
-
-    [self.popupContainer addSubview:_scrollView];
-    [_scrollView addSubview:_innerContainerView];
-    [_scrollView setAccessibilityIdentifier:@"Page Security Scroll View"];
-    [provider presentPageInfoView:self.containerView];
-    [self performLayout];
-
-    [self animatePageInfoViewIn:sourcePoint];
-    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
-                                    _containerView);
-  }
-
-  return self;
-}
-
-- (void)performLayout {
-  CGFloat offset = kInitialLinePadding;
-
-  // Keep the new subviews in an array that gets replaced at the end.
-  NSMutableArray* subviews = [NSMutableArray array];
-
-  int sectionCount = _model->GetSectionCount();
-  PageInfoModel::ButtonAction action = PageInfoModel::BUTTON_NONE;
-
-  for (int i = 0; i < sectionCount; i++) {
-    PageInfoModel::SectionInfo info = _model->GetSectionInfo(i);
-
-    if (action == PageInfoModel::BUTTON_NONE &&
-        info.button != PageInfoModel::BUTTON_NONE) {
-      // Show the button corresponding to the first section that requires a
-      // button.
-      action = info.button;
-    }
-
-    // Only certain sections have images. This affects the X position.
-    BOOL hasImage = _model->GetIconImage(info.icon_id) != nil;
-    CGFloat xPosition = (hasImage ? kTextXPosition : kTextXPositionNoImage);
-
-    // Insert the image subview for sections that are appropriate.
-    CGFloat imageBaseline = offset + kImageSize;
-    if (hasImage) {
-      [self addImageViewForInfo:info
-                     toSubviews:subviews
-                       atOffset:offset + PageInfoImageVerticalOffset()];
-    }
-
-    // Add the title.
-    if (!info.headline.empty()) {
-      offset += [self addHeadlineViewForInfo:info
-                                  toSubviews:subviews
-                                     atPoint:CGPointMake(xPosition, offset)];
-      offset += kHeadlineSpacing;
-    }
-
-    // Create the description of the state.
-    offset += [self addDescriptionViewForInfo:info
-                                   toSubviews:subviews
-                                      atPoint:CGPointMake(xPosition, offset)];
-
-    // If at this point the description and optional headline and button are
-    // not as tall as the image, adjust the offset by the difference.
-    CGFloat imageBaselineDelta = imageBaseline - offset;
-    if (imageBaselineDelta > 0)
-      offset += imageBaselineDelta;
-
-    // Add the separators.
-    int testSectionCount = sectionCount - 1;
-    if (i != testSectionCount ||
-        (i == testSectionCount && action != PageInfoModel::BUTTON_NONE)) {
-      offset += kVerticalSpacing;
-    }
-  }
-
-  // The last item at the bottom of the window is the help center link. Do not
-  // show this for the internal pages, which have one section.
-  offset += [self addButton:action toSubviews:subviews atOffset:offset];
-
-  // Add the bottom padding.
-  offset += kVerticalSpacing;
-  CGRect frame = CGRectMake(kInitialFramePosition, _arrowOriginPoint.y,
-                            _viewWidth, offset);
-
-  // Increase the size of the frame by the amount used for drawing rounded
-  // corners and shadow.
-  frame.size.height += kPageInfoViewFooterSize;
-
-  if (CGRectGetMaxY(frame) >
-      CGRectGetMaxY([[self containerView] superview].bounds) -
-          kFrameBottomPadding) {
-    // If the frame is bigger than the parent view than change the frame to
-    // fit in the superview bounds.
-    frame.size.height = [[self containerView] superview].bounds.size.height -
-                        kFrameBottomPadding - frame.origin.y;
-
-    [_scrollView setScrollEnabled:YES];
-    [_scrollView flashScrollIndicators];
-  } else {
-    [_scrollView setScrollEnabled:NO];
-  }
-
-  CGRect containerBounds = [_containerView bounds];
-  CGRect popupFrame = frame;
-  popupFrame.origin.x =
-      CGRectGetMidX(containerBounds) - CGRectGetWidth(popupFrame) / 2.0;
-  popupFrame.origin.y =
-      CGRectGetMidY(containerBounds) - CGRectGetHeight(popupFrame) / 2.0;
-
-  popupFrame.origin = AlignPointToPixel(popupFrame.origin);
-  CGRect innerFrame = CGRectMake(0, 0, popupFrame.size.width, offset);
-
-  // If the initial animation has completed, animate the new frames.
-  if (_displayAnimationCompleted) {
-    [UIView cr_animateWithDuration:ios::material::kDuration3
-                             delay:0
-                             curve:ios::material::CurveEaseInOut
-                           options:0
-                        animations:^{
-                          [_popupContainer setFrame:popupFrame];
-                          [_scrollView setFrame:[_popupContainer bounds]];
-                          [_innerContainerView setFrame:innerFrame];
-                        }
-                        completion:nil];
-  } else {
-    // Popup hasn't finished animating in yet. Set frames immediately.
-    [_popupContainer setFrame:popupFrame];
-    [_scrollView setFrame:[_popupContainer bounds]];
-    [_innerContainerView setFrame:innerFrame];
-  }
-
-  for (UIView* view in [_innerContainerView subviews]) {
-    [view removeFromSuperview];
-  }
-
-  for (UIView* view in subviews) {
-    [_innerContainerView addSubview:view];
-    [_innerContainerView setSubviewNeedsAdjustmentForRTL:view];
-  }
-
-  [_scrollView setContentSize:_innerContainerView.frame.size];
-  _closeButton.frame = _containerView.bounds;
-}
-
-- (void)dismiss {
-  [self animatePageInfoViewOut];
-  UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
-                                  nil);
-}
-
-#pragma mark - internal
-
-- (BOOL)accessibilityPerformEscape {
-  [self.dispatcher hidePageInfo];
-  return YES;
-}
-
-- (void)animatePageInfoViewIn:(CGPoint)sourcePoint {
-  // Animate the info card itself.
-  CATransform3D scaleTransform = PageInfoAnimationScale();
-
-  CABasicAnimation* scaleAnimation =
-      [CABasicAnimation animationWithKeyPath:@"transform"];
-  [scaleAnimation setFromValue:[NSValue valueWithCATransform3D:scaleTransform]];
-
-  CABasicAnimation* positionAnimation =
-      [CABasicAnimation animationWithKeyPath:@"position"];
-  [positionAnimation setFromValue:[NSValue valueWithCGPoint:sourcePoint]];
-
-  CAAnimationGroup* sizeAnimation = [CAAnimationGroup animation];
-  [sizeAnimation setAnimations:@[ scaleAnimation, positionAnimation ]];
-  [sizeAnimation
-      setTimingFunction:TimingFunction(ios::material::CurveEaseInOut)];
-  [sizeAnimation setDuration:ios::material::kDuration3];
-
-  CABasicAnimation* fadeAnimation =
-      [CABasicAnimation animationWithKeyPath:@"opacity"];
-  [fadeAnimation setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
-  [fadeAnimation setDuration:ios::material::kDuration6];
-  [fadeAnimation setFromValue:@0];
-  [fadeAnimation setToValue:@1];
-
-  [[_popupContainer layer] addAnimation:fadeAnimation forKey:@"fade"];
-  [[_popupContainer layer] addAnimation:sizeAnimation forKey:@"size"];
-
-  // Animation the background grey overlay.
-  CABasicAnimation* overlayAnimation =
-      [CABasicAnimation animationWithKeyPath:@"opacity"];
-  [overlayAnimation
-      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
-  [overlayAnimation setDuration:ios::material::kDuration3];
-  [overlayAnimation setFromValue:@0];
-  [overlayAnimation setToValue:@1];
-
-  [[_containerView layer] addAnimation:overlayAnimation forKey:@"fade"];
-  [_containerView setAlpha:1];
-
-  // Animate the contents of the info card.
-  CALayer* contentsLayer = [_innerContainerView layer];
-
-  CGRect startFrame = CGRectOffset([_innerContainerView frame], 0, -32);
-  CAAnimation* contentSlideAnimation = FrameAnimationMake(
-      contentsLayer, startFrame, [_innerContainerView frame]);
-  [contentSlideAnimation
-      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
-  [contentSlideAnimation setDuration:ios::material::kDuration5];
-  contentSlideAnimation =
-      DelayedAnimationMake(contentSlideAnimation, ios::material::kDuration2);
-  [contentsLayer addAnimation:contentSlideAnimation forKey:@"slide"];
-
-  [CATransaction begin];
-  [CATransaction setCompletionBlock:^{
-    [_innerContainerView setAlpha:1];
-    _displayAnimationCompleted = YES;
-  }];
-  CAAnimation* contentFadeAnimation = OpacityAnimationMake(0.0, 1.0);
-  [contentFadeAnimation
-      setTimingFunction:TimingFunction(ios::material::CurveEaseOut)];
-  [contentFadeAnimation setDuration:ios::material::kDuration5];
-  contentFadeAnimation =
-      DelayedAnimationMake(contentFadeAnimation, ios::material::kDuration1);
-  [contentsLayer addAnimation:contentFadeAnimation forKey:@"fade"];
-  [CATransaction commit];
-
-  // Since the animations have delay on them, the alpha of the content view
-  // needs to be set to zero and then one after the animation starts. If these
-  // steps are not taken, there will be a visible flash/jump from the initial
-  // spot during the animation.
-  [_innerContainerView setAlpha:0];
-}
-
-- (void)animatePageInfoViewOut {
-  [CATransaction begin];
-  [CATransaction setCompletionBlock:^{
-    [self.containerView removeFromSuperview];
-  }];
-
-  CABasicAnimation* opacityAnimation =
-      [CABasicAnimation animationWithKeyPath:@"opacity"];
-  [opacityAnimation
-      setTimingFunction:TimingFunction(ios::material::CurveEaseIn)];
-  [opacityAnimation setDuration:ios::material::kDuration3];
-  [opacityAnimation setFromValue:@1];
-  [opacityAnimation setToValue:@0];
-  [[_containerView layer] addAnimation:opacityAnimation forKey:@"animateOut"];
-
-  [_popupContainer setAlpha:0];
-  [_containerView setAlpha:0];
-  [CATransaction commit];
-}
-
-#pragma mark - Helper methods to create subviews.
-
-// Adds the state image at a pre-determined x position and the given y. This
-// does not affect the next Y position because the image is placed next to
-// a text field that is larger and accounts for the image's size.
-- (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
-                 toSubviews:(NSMutableArray*)subviews
-                   atOffset:(CGFloat)offset {
-  CGRect frame = CGRectMake(kFramePadding, offset, kImageSize, kImageSize);
-  UIImageView* imageView = [[UIImageView alloc] initWithFrame:frame];
-  imageView.tintColor = UIColor.cr_labelColor;
-  UIImage* image = [_model->GetIconImage(info.icon_id)->ToUIImage()
-      imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
-  [imageView setImage:image];
-  [subviews addObject:imageView];
-}
-
-// Adds the title text field at the given x,y position, and returns the y
-// position for the next element.
-- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info
-                       toSubviews:(NSMutableArray*)subviews
-                          atPoint:(CGPoint)point {
-  CGRect frame = CGRectMake(point.x, point.y, _textWidth, kHeadlineHeight);
-  UILabel* label = [[UILabel alloc] initWithFrame:frame];
-  [label setTextAlignment:NSTextAlignmentNatural];
-  [label setText:base::SysUTF16ToNSString(info.headline)];
-  [label setTextColor:UIColor.cr_labelColor];
-  [label setFont:PageInfoHeadlineFont()];
-  [label setFrame:frame];
-  [label setLineBreakMode:NSLineBreakByTruncatingHead];
-  [subviews addObject:label];
-  return CGRectGetHeight(frame);
-}
-
-// Adds the description text field at the given x,y position, and returns the y
-// position for the next element.
-- (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info
-                          toSubviews:(NSMutableArray*)subviews
-                             atPoint:(CGPoint)point {
-  CGRect frame = CGRectMake(point.x, point.y, _textWidth, kImageSize);
-  UILabel* label = [[UILabel alloc] initWithFrame:frame];
-  [label setTextAlignment:NSTextAlignmentNatural];
-  NSString* description = base::SysUTF16ToNSString(info.description);
-  UIFont* font = [MDCTypography captionFont];
-  [label setTextColor:UIColor.cr_labelColor];
-  [label setText:description];
-  [label setFont:font];
-  [label setNumberOfLines:0];
-
-  // If the text is oversized, resize the text field.
-  CGSize constraintSize = CGSizeMake(_textWidth, CGFLOAT_MAX);
-  CGSize sizeToFit =
-      [description cr_boundingSizeWithSize:constraintSize font:font];
-  frame.size.height = sizeToFit.height;
-  [label setFrame:frame];
-  [subviews addObject:label];
-  return CGRectGetHeight(frame);
-}
-
-// Returns a button with title and action configured for |buttonAction|.
-- (UIButton*)buttonForAction:(PageInfoModel::ButtonAction)buttonAction {
-  if (buttonAction == PageInfoModel::BUTTON_NONE) {
-    return nil;
-  }
-  UIButton* button = [[UIButton alloc] initWithFrame:CGRectZero];
-  int messageId;
-  NSString* accessibilityID = @"Reload button";
-  switch (buttonAction) {
-    case PageInfoModel::BUTTON_NONE:
-      NOTREACHED();
-      return nil;
-    case PageInfoModel::BUTTON_SHOW_SECURITY_HELP:
-      messageId = IDS_LEARN_MORE;
-      accessibilityID = @"Learn more";
-      [button addTarget:self.dispatcher
-                    action:@selector(showSecurityHelpPage)
-          forControlEvents:UIControlEventTouchUpInside];
-      break;
-    case PageInfoModel::BUTTON_RELOAD:
-      messageId = IDS_IOS_PAGE_INFO_RELOAD;
-      accessibilityID = @"Reload button";
-      [button addTarget:self.dispatcher
-                    action:@selector(hidePageInfo)
-          forControlEvents:UIControlEventTouchUpInside];
-      [button addTarget:self.dispatcher
-                    action:@selector(reload)
-          forControlEvents:UIControlEventTouchUpInside];
-      break;
-  };
-
-  NSString* title = l10n_util::GetNSStringWithFixup(messageId);
-  SetA11yLabelAndUiAutomationName(button, messageId, accessibilityID);
-  [button setTitle:title forState:UIControlStateNormal];
-  return button;
-}
-
-// Adds the the button |buttonAction| that explains the icons. Returns the y
-// position delta for the next offset.
-- (CGFloat)addButton:(PageInfoModel::ButtonAction)buttonAction
-          toSubviews:(NSMutableArray*)subviews
-            atOffset:(CGFloat)offset {
-  UIButton* button = [self buttonForAction:buttonAction];
-  if (!button) {
-    return 0;
-  }
-  // The size of the initial frame is irrelevant since it will be changed based
-  // on the size for the string inside.
-  CGRect frame = CGRectMake(kButtonXOffset, offset, 100, 10);
-
-  UIFont* font = [MDCTypography captionFont];
-  CGSize sizeWithFont =
-      [[[button titleLabel] text] cr_pixelAlignedSizeWithFont:font];
-  frame.size = sizeWithFont;
-  // According to iOS Human Interface Guidelines, minimal size of UIButton
-  // should be 44x44.
-  frame.size.height = std::max<CGFloat>(44, frame.size.height);
-
-  [button setFrame:frame];
-
-  [button.titleLabel setFont:font];
-  [button.titleLabel setTextAlignment:NSTextAlignmentLeft];
-  [button setTitleColor:[UIColor colorNamed:kBlueColor]
-               forState:UIControlStateNormal];
-  [button setTitleColor:[UIColor colorNamed:kBlueColor]
-               forState:UIControlStateSelected];
-
-  [subviews addObject:button];
-
-  return CGRectGetHeight([button frame]);
-}
-
 @end
diff --git a/ios/chrome/browser/ui/page_info/requirements/BUILD.gn b/ios/chrome/browser/ui/page_info/requirements/BUILD.gn
index 82032f2..789a97e 100644
--- a/ios/chrome/browser/ui/page_info/requirements/BUILD.gn
+++ b/ios/chrome/browser/ui/page_info/requirements/BUILD.gn
@@ -6,6 +6,5 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "page_info_presentation.h",
-    "page_info_reloading.h",
   ]
 }
diff --git a/ios/chrome/browser/ui/page_info/requirements/page_info_reloading.h b/ios/chrome/browser/ui/page_info/requirements/page_info_reloading.h
deleted file mode 100644
index ef6012a..0000000
--- a/ios/chrome/browser/ui/page_info/requirements/page_info_reloading.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_REQUIREMENTS_PAGE_INFO_RELOADING_H_
-#define IOS_CHROME_BROWSER_UI_PAGE_INFO_REQUIREMENTS_PAGE_INFO_RELOADING_H_
-
-// PageInfoReloading contains methods related to reloading a web page.
-@protocol PageInfoReloading
-
-// Reloads the web page.
-- (void)reload;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_PAGE_INFO_REQUIREMENTS_PAGE_INFO_RELOADING_H_
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn
index 59f7ef6..2d0e9af 100644
--- a/ios/chrome/browser/ui/popup_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -65,6 +65,7 @@
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/ntp_tile_views:constants",
+    "//ios/chrome/browser/ui/page_info:features",
     "//ios/chrome/browser/ui/popup_menu/cells",
     "//ios/chrome/browser/ui/popup_menu/public",
     "//ios/chrome/browser/ui/popup_menu/public:popup_menu_ui",
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
index 3e364be6..5a22aac 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
@@ -14,6 +14,7 @@
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/load_query_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
+#import "ios/chrome/browser/ui/page_info/features.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_commands.h"
 #import "ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h"
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.h"
@@ -84,8 +85,13 @@
       break;
     case PopupMenuActionSiteInformation:
       RecordAction(UserMetricsAction("MobileMenuSiteInformation"));
-      [self.dispatcher
-          showPageInfoForOriginPoint:self.baseViewController.view.center];
+      if (base::FeatureList::IsEnabled(kPageInfoRefactoring)) {
+        [self.dispatcher showPageInfo];
+      } else {
+        [self.dispatcher
+            legacyShowPageInfoForOriginPoint:self.baseViewController.view
+                                                 .center];
+      }
       break;
     case PopupMenuActionReportIssue:
       RecordAction(UserMetricsAction("MobileMenuReportAnIssue"));
diff --git a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm
index a11fd04c..7ecae137 100644
--- a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm
+++ b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm
@@ -32,7 +32,7 @@
 
 // Custom timeout used when waiting for a web state after requesting desktop
 // or mobile mode.
-const NSTimeInterval kWaitForUserAgentChangeTimeout = 10.0;
+const NSTimeInterval kWaitForUserAgentChangeTimeout = 15.0;
 
 // Select the button to request desktop site by scrolling the collection.
 // 200 is a reasonable scroll displacement that works for all UI elements, while
@@ -169,15 +169,7 @@
 
 // Tests that requesting mobile site of a page works and the user agent
 // propagates to the next navigations in the same tab.
-// TODO(crbug.com/1037663): Enable for EG2.
-#if defined(CHROME_EARL_GREY_2)
-#define MAYBE_testRequestMobileSitePropagatesToNextNavigations \
-  FLAKY_testRequestMobileSitePropagatesToNextNavigations
-#else
-#define MAYBE_testRequestMobileSitePropagatesToNextNavigations \
-  testRequestMobileSitePropagatesToNextNavigations
-#endif
-- (void)MAYBE_testRequestMobileSitePropagatesToNextNavigations {
+- (void)testRequestMobileSitePropagatesToNextNavigations {
   std::unique_ptr<web::DataResponseProvider> provider(
       new UserAgentResponseProvider());
   web::test::SetUpHttpServer(std::move(provider));
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h
index d2d5ea3..31cb113a 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h
@@ -10,8 +10,7 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_switcher.h"
 
-@protocol TabGridPaging;
-@class TabGridURLLoader;
+@class TabGridViewController;
 
 // An opaque adaptor for the TabSwitcher protocol into the TabGrid.
 // Consuming objects should be passed instances of this object as an
@@ -19,18 +18,9 @@
 // All of the methods and properties on this class are internal API fot the
 // tab grid, and external code shouldn't depend on them.
 @interface TabGridAdaptor : NSObject<TabSwitcher>
-@property(nonatomic, weak) UIViewController* tabGridViewController;
-// Dispatcher object this adaptor will expose as the dispacther for the
-// TabSwitcher protocol.
-@property(nonatomic, weak)
-    id<ApplicationCommands, OmniboxFocuser, ToolbarCommands>
-        adaptedDispatcher;
-// Object that can set the current page of the tab grid.
-@property(nonatomic, weak) id<TabGridPaging> tabGridPager;
+@property(nonatomic, weak) TabGridViewController* tabGridViewController;
 // The mediator for the incognito grid.
 @property(nonatomic, weak) TabGridMediator* incognitoMediator;
-// Specialized URL loader for tab grid.
-@property(nonatomic, weak) TabGridURLLoader* loader;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
index 52059d3e..0875518 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
@@ -8,11 +8,11 @@
 #import "ios/chrome/browser/main/browser.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
 #import "ios/chrome/browser/ui/tab_grid/view_controller_swapping.h"
 #import "ios/chrome/browser/url_loading/url_loading_params.h"
 #import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
-
 #import "ios/web/public/navigation/navigation_manager.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -25,20 +25,15 @@
 
 #pragma mark - TabSwitcher
 
-- (id<ApplicationCommands, OmniboxFocuser, ToolbarCommands>)dispatcher {
-  return static_cast<id<ApplicationCommands, OmniboxFocuser, ToolbarCommands>>(
-      self.adaptedDispatcher);
-}
-
 - (void)restoreInternalStateWithMainTabModel:(TabModel*)mainModel
                                  otrTabModel:(TabModel*)otrModel
                               activeTabModel:(TabModel*)activeModel {
   // The only action here is to signal to the tab grid which panel should be
   // active.
   if (activeModel == otrModel) {
-    self.tabGridPager.activePage = TabGridPageIncognitoTabs;
+    self.tabGridViewController.activePage = TabGridPageIncognitoTabs;
   } else {
-    self.tabGridPager.activePage = TabGridPageRegularTabs;
+    self.tabGridViewController.activePage = TabGridPageRegularTabs;
   }
 }
 
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index 31e191f..db97b060 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -151,10 +151,6 @@
 
   self.adaptor = [[TabGridAdaptor alloc] init];
   self.adaptor.tabGridViewController = self.baseViewController;
-  self.adaptor.adaptedDispatcher =
-      static_cast<id<ApplicationCommands, OmniboxFocuser, ToolbarCommands>>(
-          self.dispatcher);
-  self.adaptor.tabGridPager = baseViewController;
 
   self.regularTabsMediator = [[TabGridMediator alloc]
       initWithConsumer:baseViewController.regularTabsConsumer];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_switcher.h b/ios/chrome/browser/ui/tab_grid/tab_switcher.h
index f7628dac..7d938a5 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_switcher.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_switcher.h
@@ -12,10 +12,8 @@
 #include "url/gurl.h"
 
 class Browser;
-@protocol OmniboxFocuser;
 @class TabModel;
 @protocol TabSwitcher;
-@protocol ToolbarCommands;
 struct UrlLoadParams;
 
 // This delegate is used to drive the TabSwitcher dismissal and execute code
@@ -44,11 +42,6 @@
 // switcher.
 @property(nonatomic, weak) id<TabSwitcherDelegate> delegate;
 
-// Dispatcher for anything that acts in a "browser" role.
-@property(nonatomic, readonly)
-    id<ApplicationCommands, OmniboxFocuser, ToolbarCommands>
-        dispatcher;
-
 // Restores the internal state of the tab switcher with the given tab models,
 // which must not be nil. |activeTabModel| is the model which starts active,
 // and must be one of the other two models. Should only be called when the
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index d31098b4..0ac1307 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -266,6 +266,8 @@
     "//ios/chrome/browser/ui/open_in:unit_tests",
     "//ios/chrome/browser/ui/overlays:unit_tests",
     "//ios/chrome/browser/ui/overlays/common/alerts:unit_tests",
+    "//ios/chrome/browser/ui/overlays/infobar_banner:unit_tests",
+    "//ios/chrome/browser/ui/overlays/infobar_banner/passwords:unit_tests",
     "//ios/chrome/browser/ui/overlays/web_content_area/app_launcher:unit_tests",
     "//ios/chrome/browser/ui/overlays/web_content_area/http_auth_dialogs:unit_tests",
     "//ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs:unit_tests",
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h
index b3e9477..2ea846e 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.h
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -40,6 +40,7 @@
 @protocol LogoVendor;
 @class UITextField;
 @class UIView;
+class Browser;
 
 namespace ios {
 
@@ -120,6 +121,9 @@
   // Attaches any embedder-specific tab helpers to the given |web_state|.
   virtual void AttachTabHelpers(web::WebState* web_state) const;
 
+  // Attaches any embedder-specific browser agents to the given |browser|.
+  virtual void AttachBrowserAgents(Browser* browser) const;
+
   // Returns an instance of the voice search provider, if one exists.
   virtual VoiceSearchProvider* GetVoiceSearchProvider() const;
 
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
index c4bd1d82..40ddd84e 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -84,6 +84,8 @@
 
 void ChromeBrowserProvider::AttachTabHelpers(web::WebState* web_state) const {}
 
+void ChromeBrowserProvider::AttachBrowserAgents(Browser* browser) const {}
+
 VoiceSearchProvider* ChromeBrowserProvider::GetVoiceSearchProvider() const {
   return nullptr;
 }
diff --git a/media/base/audio_renderer.h b/media/base/audio_renderer.h
index 5a50bb3..eac3c82 100644
--- a/media/base/audio_renderer.h
+++ b/media/base/audio_renderer.h
@@ -41,7 +41,7 @@
   virtual void Initialize(DemuxerStream* stream,
                           CdmContext* cdm_context,
                           RendererClient* client,
-                          const PipelineStatusCB& init_cb) = 0;
+                          PipelineStatusCallback init_cb) = 0;
 
   // Returns the TimeSource associated with audio rendering.
   virtual TimeSource* GetTimeSource() = 0;
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index 226bca6..77d9711 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -77,12 +77,25 @@
   MockPipeline();
   ~MockPipeline() override;
 
-  MOCK_METHOD4(Start,
-               void(StartType, Demuxer*, Client*, const PipelineStatusCB&));
+  void Start(StartType start_type,
+             Demuxer* demuxer,
+             Client* client,
+             PipelineStatusCallback seek_cb) {
+    OnStart(start_type, demuxer, client, seek_cb);
+  }
+  MOCK_METHOD4(OnStart,
+               void(StartType, Demuxer*, Client*, PipelineStatusCallback&));
   MOCK_METHOD0(Stop, void());
-  MOCK_METHOD2(Seek, void(base::TimeDelta, const PipelineStatusCB&));
-  MOCK_METHOD1(Suspend, void(const PipelineStatusCB&));
-  MOCK_METHOD2(Resume, void(base::TimeDelta, const PipelineStatusCB&));
+  void Seek(base::TimeDelta time, PipelineStatusCallback seek_cb) {
+    OnSeek(time, seek_cb);
+  }
+  MOCK_METHOD2(OnSeek, void(base::TimeDelta, PipelineStatusCallback&));
+  void Suspend(PipelineStatusCallback cb) { OnSuspend(cb); }
+  MOCK_METHOD1(OnSuspend, void(PipelineStatusCallback&));
+  void Resume(base::TimeDelta time, PipelineStatusCallback seek_cb) {
+    OnResume(time, seek_cb);
+  }
+  MOCK_METHOD2(OnResume, void(base::TimeDelta, PipelineStatusCallback&));
   MOCK_METHOD2(OnEnabledAudioTracksChanged,
                void(const std::vector<MediaTrack::Id>&, base::OnceClosure));
   MOCK_METHOD2(OnSelectedVideoTrackChanged,
@@ -294,12 +307,19 @@
   ~MockVideoRenderer() override;
 
   // VideoRenderer implementation.
-  MOCK_METHOD5(Initialize,
+  void Initialize(DemuxerStream* stream,
+                  CdmContext* cdm_context,
+                  RendererClient* client,
+                  const TimeSource::WallClockTimeCB& wall_clock_time_cb,
+                  PipelineStatusCallback init_cb) {
+    OnInitialize(stream, cdm_context, client, wall_clock_time_cb, init_cb);
+  }
+  MOCK_METHOD5(OnInitialize,
                void(DemuxerStream* stream,
                     CdmContext* cdm_context,
                     RendererClient* client,
                     const TimeSource::WallClockTimeCB& wall_clock_time_cb,
-                    const PipelineStatusCB& init_cb));
+                    PipelineStatusCallback& init_cb));
   MOCK_METHOD1(Flush, void(base::OnceClosure flush_cb));
   MOCK_METHOD1(StartPlayingFrom, void(base::TimeDelta));
   MOCK_METHOD0(OnTimeProgressing, void());
@@ -315,11 +335,17 @@
   ~MockAudioRenderer() override;
 
   // AudioRenderer implementation.
-  MOCK_METHOD4(Initialize,
+  void Initialize(DemuxerStream* stream,
+                  CdmContext* cdm_context,
+                  RendererClient* client,
+                  PipelineStatusCallback init_cb) {
+    OnInitialize(stream, cdm_context, client, init_cb);
+  }
+  MOCK_METHOD4(OnInitialize,
                void(DemuxerStream* stream,
                     CdmContext* cdm_context,
                     RendererClient* client,
-                    const PipelineStatusCB& init_cb));
+                    PipelineStatusCallback& init_cb));
   MOCK_METHOD0(GetTimeSource, TimeSource*());
   MOCK_METHOD1(Flush, void(base::OnceClosure flush_cb));
   MOCK_METHOD0(StartPlaying, void());
diff --git a/media/base/pipeline.h b/media/base/pipeline.h
index fccf9f08..fbd6575e 100644
--- a/media/base/pipeline.h
+++ b/media/base/pipeline.h
@@ -111,7 +111,7 @@
   virtual void Start(StartType start_type,
                      Demuxer* demuxer,
                      Client* client,
-                     const PipelineStatusCB& seek_cb) = 0;
+                     PipelineStatusCallback seek_cb) = 0;
 
   // Track switching works similarly for both audio and video. Callbacks are
   // used to notify when it is time to procede to the next step, since many of
@@ -168,7 +168,7 @@
   //
   // It is an error to call this method if the pipeline has not started or
   // has been suspended.
-  virtual void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) = 0;
+  virtual void Seek(base::TimeDelta time, PipelineStatusCallback seek_cb) = 0;
 
   // Suspends the pipeline, discarding the current renderer.
   //
@@ -177,14 +177,14 @@
   //
   // It is an error to call this method if the pipeline has not started or is
   // seeking.
-  virtual void Suspend(const PipelineStatusCB& suspend_cb) = 0;
+  virtual void Suspend(PipelineStatusCallback suspend_cb) = 0;
 
   // Resume the pipeline and seek to |timestamp|.
   //
   // It is an error to call this method if the pipeline has not finished
   // suspending.
   virtual void Resume(base::TimeDelta timestamp,
-                      const PipelineStatusCB& seek_cb) = 0;
+                      PipelineStatusCallback seek_cb) = 0;
 
   // Returns true if the pipeline has been started via Start().  If IsRunning()
   // returns true, it is expected that Stop() will be called before destroying
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index 8095cdb..4a10685d 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -1161,7 +1161,7 @@
 void PipelineImpl::Start(StartType start_type,
                          Demuxer* demuxer,
                          Client* client,
-                         const PipelineStatusCB& seek_cb) {
+                         PipelineStatusCallback seek_cb) {
   DVLOG(2) << __func__ << ": start_type=" << static_cast<int>(start_type);
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(demuxer);
@@ -1171,7 +1171,7 @@
   DCHECK(!client_);
   DCHECK(!seek_cb_);
   client_ = client;
-  seek_cb_ = seek_cb;
+  seek_cb_ = std::move(seek_cb);
   last_media_time_ = base::TimeDelta();
   seek_time_ = kNoTimestamp;
 
@@ -1222,19 +1222,19 @@
   weak_factory_.InvalidateWeakPtrs();
 }
 
-void PipelineImpl::Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) {
+void PipelineImpl::Seek(base::TimeDelta time, PipelineStatusCallback seek_cb) {
   DVLOG(2) << __func__ << " to " << time.InMicroseconds();
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(seek_cb);
 
   if (!IsRunning()) {
     DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
-    seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
+    std::move(seek_cb).Run(PIPELINE_ERROR_INVALID_STATE);
     return;
   }
 
   DCHECK(!seek_cb_);
-  seek_cb_ = seek_cb;
+  seek_cb_ = std::move(seek_cb);
   seek_time_ = time;
   last_media_time_ = base::TimeDelta();
   media_task_runner_->PostTask(
@@ -1243,13 +1243,13 @@
                      base::Unretained(renderer_wrapper_.get()), time));
 }
 
-void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) {
+void PipelineImpl::Suspend(PipelineStatusCallback suspend_cb) {
   DVLOG(2) << __func__;
   DCHECK(suspend_cb);
 
   DCHECK(IsRunning());
   DCHECK(!suspend_cb_);
-  suspend_cb_ = suspend_cb;
+  suspend_cb_ = std::move(suspend_cb);
 
   media_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&RendererWrapper::Suspend,
@@ -1257,14 +1257,14 @@
 }
 
 void PipelineImpl::Resume(base::TimeDelta time,
-                          const PipelineStatusCB& seek_cb) {
+                          PipelineStatusCallback seek_cb) {
   DVLOG(2) << __func__;
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(seek_cb);
 
   DCHECK(IsRunning());
   DCHECK(!seek_cb_);
-  seek_cb_ = seek_cb;
+  seek_cb_ = std::move(seek_cb);
   seek_time_ = time;
   last_media_time_ = base::TimeDelta();
 
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h
index e190261c..101de818 100644
--- a/media/base/pipeline_impl.h
+++ b/media/base/pipeline_impl.h
@@ -92,11 +92,11 @@
   void Start(StartType start_type,
              Demuxer* demuxer,
              Client* client,
-             const PipelineStatusCB& seek_cb) override;
+             PipelineStatusCallback seek_cb) override;
   void Stop() override;
-  void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) override;
-  void Suspend(const PipelineStatusCB& suspend_cb) override;
-  void Resume(base::TimeDelta time, const PipelineStatusCB& seek_cb) override;
+  void Seek(base::TimeDelta time, PipelineStatusCallback seek_cb) override;
+  void Suspend(PipelineStatusCallback suspend_cb) override;
+  void Resume(base::TimeDelta time, PipelineStatusCallback seek_cb) override;
   bool IsRunning() const override;
   bool IsSuspended() const override;
   double GetPlaybackRate() const override;
@@ -181,10 +181,10 @@
   std::unique_ptr<RendererWrapper> renderer_wrapper_;
 
   // Temporary callback used for Start(), Seek(), and Resume().
-  PipelineStatusCB seek_cb_;
+  PipelineStatusCallback seek_cb_;
 
   // Temporary callback used for Suspend().
-  PipelineStatusCB suspend_cb_;
+  PipelineStatusCallback suspend_cb_;
 
   // Current playback rate (>= 0.0). This value is set immediately via
   // SetPlaybackRate() and a task is dispatched on the task runner to notify
diff --git a/media/base/test_helpers.cc b/media/base/test_helpers.cc
index 385c888e..f7958455 100644
--- a/media/base/test_helpers.cc
+++ b/media/base/test_helpers.cc
@@ -57,10 +57,10 @@
   return base::BindOnce(&MockCallback::RunWithBool, WrapRefCounted(callback));
 }
 
-PipelineStatusCB NewExpectedStatusCB(PipelineStatus status) {
+PipelineStatusCallback NewExpectedStatusCB(PipelineStatus status) {
   StrictMock<MockCallback>* callback = new StrictMock<MockCallback>();
   EXPECT_CALL(*callback, RunWithStatus(status));
-  return base::Bind(&MockCallback::RunWithStatus, WrapRefCounted(callback));
+  return base::BindOnce(&MockCallback::RunWithStatus, WrapRefCounted(callback));
 }
 
 WaitableMessageLoopEvent::WaitableMessageLoopEvent()
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h
index ba66598c..4279889 100644
--- a/media/base/test_helpers.h
+++ b/media/base/test_helpers.h
@@ -38,7 +38,7 @@
 // Return a callback that expects to be run once.
 base::OnceClosure NewExpectedClosure();
 base::OnceCallback<void(bool)> NewExpectedBoolCB(bool success);
-PipelineStatusCB NewExpectedStatusCB(PipelineStatus status);
+PipelineStatusCallback NewExpectedStatusCB(PipelineStatus status);
 
 // Helper class for running a message loop until a callback has run. Useful for
 // testing classes that run on more than a single thread.
diff --git a/media/base/video_renderer.h b/media/base/video_renderer.h
index c8268c5..7a7fc29 100644
--- a/media/base/video_renderer.h
+++ b/media/base/video_renderer.h
@@ -42,7 +42,7 @@
                           CdmContext* cdm_context,
                           RendererClient* client,
                           const TimeSource::WallClockTimeCB& wall_clock_time_cb,
-                          const PipelineStatusCB& init_cb) = 0;
+                          PipelineStatusCallback init_cb) = 0;
 
   // Discards any video data and stops reading from |stream|, executing
   // |callback| when completed.
diff --git a/media/filters/pipeline_controller_unittest.cc b/media/filters/pipeline_controller_unittest.cc
index 0bb2fbe..0192c79 100644
--- a/media/filters/pipeline_controller_unittest.cc
+++ b/media/filters/pipeline_controller_unittest.cc
@@ -30,6 +30,17 @@
 using ::testing::SaveArg;
 using ::testing::StrictMock;
 
+namespace {
+
+// Like SaveArg, but for an argument that needs to be moved.
+ACTION_TEMPLATE(MoveArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = std::move(::std::get<k>(args));
+}
+
+}  // namespace
+
 namespace media {
 
 class PipelineControllerTest : public ::testing::Test, public Pipeline::Client {
@@ -50,10 +61,11 @@
 
   ~PipelineControllerTest() override = default;
 
-  PipelineStatusCB StartPipeline(bool is_streaming, bool is_static) {
+  PipelineStatusCallback StartPipeline(bool is_streaming, bool is_static) {
     EXPECT_FALSE(pipeline_controller_.IsStable());
-    PipelineStatusCB start_cb;
-    EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb));
+    PipelineStatusCallback start_cb;
+    EXPECT_CALL(*pipeline_, OnStart(_, _, _, _))
+        .WillOnce(MoveArg<3>(&start_cb));
     pipeline_controller_.Start(Pipeline::StartType::kNormal, &demuxer_, this,
                                is_streaming, is_static);
     Mock::VerifyAndClear(pipeline_);
@@ -64,30 +76,30 @@
     return start_cb;
   }
 
-  PipelineStatusCB StartPipeline() { return StartPipeline(false, true); }
+  PipelineStatusCallback StartPipeline() { return StartPipeline(false, true); }
 
-  PipelineStatusCB StartPipeline_WithDynamicData() {
+  PipelineStatusCallback StartPipeline_WithDynamicData() {
     return StartPipeline(false, false);
   }
 
-  PipelineStatusCB StartPipeline_WithStreamingData() {
+  PipelineStatusCallback StartPipeline_WithStreamingData() {
     return StartPipeline(true, false);
   }
 
-  PipelineStatusCB SeekPipeline(base::TimeDelta time) {
+  PipelineStatusCallback SeekPipeline(base::TimeDelta time) {
     EXPECT_TRUE(pipeline_controller_.IsStable());
-    PipelineStatusCB seek_cb;
-    EXPECT_CALL(*pipeline_, Seek(time, _)).WillOnce(SaveArg<1>(&seek_cb));
+    PipelineStatusCallback seek_cb;
+    EXPECT_CALL(*pipeline_, OnSeek(time, _)).WillOnce(MoveArg<1>(&seek_cb));
     pipeline_controller_.Seek(time, true);
     Mock::VerifyAndClear(pipeline_);
     EXPECT_FALSE(pipeline_controller_.IsStable());
     return seek_cb;
   }
 
-  PipelineStatusCB SuspendPipeline() {
+  PipelineStatusCallback SuspendPipeline() {
     EXPECT_TRUE(pipeline_controller_.IsStable());
-    PipelineStatusCB suspend_cb;
-    EXPECT_CALL(*pipeline_, Suspend(_)).WillOnce(SaveArg<0>(&suspend_cb));
+    PipelineStatusCallback suspend_cb;
+    EXPECT_CALL(*pipeline_, OnSuspend(_)).WillOnce(MoveArg<0>(&suspend_cb));
     pipeline_controller_.Suspend();
     Mock::VerifyAndClear(pipeline_);
     EXPECT_CALL(*pipeline_, IsSuspended())
@@ -99,12 +111,12 @@
     return suspend_cb;
   }
 
-  PipelineStatusCB ResumePipeline() {
+  PipelineStatusCallback ResumePipeline() {
     EXPECT_TRUE(pipeline_controller_.IsPipelineSuspended());
-    PipelineStatusCB resume_cb;
-    EXPECT_CALL(*pipeline_, Resume(_, _))
+    PipelineStatusCallback resume_cb;
+    EXPECT_CALL(*pipeline_, OnResume(_, _))
         .WillOnce(
-            DoAll(SaveArg<0>(&last_resume_time_), SaveArg<1>(&resume_cb)));
+            DoAll(SaveArg<0>(&last_resume_time_), MoveArg<1>(&resume_cb)));
     EXPECT_CALL(*pipeline_, GetMediaTime())
         .WillRepeatedly(Return(base::TimeDelta()));
     pipeline_controller_.Resume();
@@ -118,8 +130,8 @@
     return resume_cb;
   }
 
-  void Complete(const PipelineStatusCB& cb) {
-    cb.Run(PIPELINE_OK);
+  void Complete(PipelineStatusCallback cb) {
+    std::move(cb).Run(PIPELINE_OK);
     base::RunLoop().RunUntilIdle();
   }
 
@@ -169,10 +181,10 @@
 };
 
 TEST_F(PipelineControllerTest, Startup) {
-  PipelineStatusCB start_cb = StartPipeline();
+  PipelineStatusCallback start_cb = StartPipeline();
   EXPECT_FALSE(was_seeked_);
 
-  Complete(start_cb);
+  Complete(std::move(start_cb));
   EXPECT_TRUE(was_seeked_);
   EXPECT_FALSE(last_seeked_time_updated_);
   EXPECT_FALSE(was_suspended_);
@@ -181,8 +193,8 @@
 
 TEST_F(PipelineControllerTest, StartSuspendedSeekAndResume) {
   EXPECT_FALSE(pipeline_controller_.IsStable());
-  PipelineStatusCB start_cb;
-  EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb));
+  PipelineStatusCallback start_cb;
+  EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
   pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
                              &demuxer_, this, false, true);
   Mock::VerifyAndClear(pipeline_);
@@ -194,14 +206,15 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(was_seeked_);
 
-  PipelineStatusCB resume_cb;
-  EXPECT_CALL(*pipeline_, Resume(_, _)).WillOnce(DoAll(SaveArg<1>(&resume_cb)));
+  PipelineStatusCallback resume_cb;
+  EXPECT_CALL(*pipeline_, OnResume(_, _))
+      .WillOnce(DoAll(MoveArg<1>(&resume_cb)));
   EXPECT_CALL(*pipeline_, GetMediaTime())
       .WillRepeatedly(Return(base::TimeDelta()));
 
   EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
   EXPECT_FALSE(pipeline_controller_.IsStable());
-  Complete(start_cb);
+  Complete(std::move(start_cb));
 
   EXPECT_FALSE(pipeline_controller_.IsStable());
   EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
@@ -209,7 +222,7 @@
   Mock::VerifyAndClear(pipeline_);
 
   EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
-  Complete(resume_cb);
+  Complete(std::move(resume_cb));
   EXPECT_TRUE(was_seeked_);
   was_seeked_ = false;
 
@@ -221,14 +234,14 @@
 
 TEST_F(PipelineControllerTest, StartSuspendedAndResume) {
   EXPECT_FALSE(pipeline_controller_.IsStable());
-  PipelineStatusCB start_cb;
-  EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb));
+  PipelineStatusCallback start_cb;
+  EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
   pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
                              &demuxer_, this, false, true);
   Mock::VerifyAndClear(pipeline_);
   EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
   EXPECT_FALSE(pipeline_controller_.IsStable());
-  Complete(start_cb);
+  Complete(std::move(start_cb));
   EXPECT_TRUE(was_seeked_);
   was_seeked_ = false;
 
@@ -238,11 +251,11 @@
   Mock::VerifyAndClear(pipeline_);
 
   EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
-  PipelineStatusCB resume_cb = ResumePipeline();
+  PipelineStatusCallback resume_cb = ResumePipeline();
   EXPECT_TRUE(was_resuming_);
   EXPECT_FALSE(was_resumed_);
 
-  Complete(resume_cb);
+  Complete(std::move(resume_cb));
   EXPECT_TRUE(was_resumed_);
   EXPECT_TRUE(pipeline_controller_.IsStable());
 
@@ -259,11 +272,11 @@
   EXPECT_TRUE(was_suspended_);
   EXPECT_FALSE(pipeline_controller_.IsStable());
 
-  PipelineStatusCB resume_cb = ResumePipeline();
+  PipelineStatusCallback resume_cb = ResumePipeline();
   EXPECT_TRUE(was_resuming_);
   EXPECT_FALSE(was_resumed_);
 
-  Complete(resume_cb);
+  Complete(std::move(resume_cb));
   EXPECT_TRUE(was_resumed_);
   EXPECT_TRUE(pipeline_controller_.IsStable());
 
@@ -280,11 +293,11 @@
 
   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
   EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time));
-  PipelineStatusCB seek_cb = SeekPipeline(seek_time);
+  PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(was_seeked_);
 
-  Complete(seek_cb);
+  Complete(std::move(seek_cb));
   EXPECT_TRUE(was_seeked_);
   EXPECT_TRUE(pipeline_controller_.IsStable());
 }
@@ -298,7 +311,7 @@
       .WillRepeatedly(Return(kCurrentMediaTime));
 
   EXPECT_CALL(demuxer_, StartWaitingForSeek(kCurrentMediaTime));
-  EXPECT_CALL(*pipeline_, Seek(kCurrentMediaTime, _));
+  EXPECT_CALL(*pipeline_, OnSeek(kCurrentMediaTime, _));
 
   pipeline_controller_.OnDecoderStateLost();
   base::RunLoop().RunUntilIdle();
@@ -311,7 +324,7 @@
   // Create a pending seek.
   base::TimeDelta kSeekTime = base::TimeDelta::FromSeconds(5);
   EXPECT_CALL(demuxer_, StartWaitingForSeek(kSeekTime));
-  PipelineStatusCB seek_cb = SeekPipeline(kSeekTime);
+  PipelineStatusCallback seek_cb = SeekPipeline(kSeekTime);
   base::RunLoop().RunUntilIdle();
   Mock::VerifyAndClear(&demuxer_);
 
@@ -320,7 +333,7 @@
   pipeline_controller_.OnDecoderStateLost();
   base::RunLoop().RunUntilIdle();
 
-  Complete(seek_cb);
+  Complete(std::move(seek_cb));
 }
 
 TEST_F(PipelineControllerTest, SuspendResumeTime) {
@@ -353,7 +366,7 @@
   // Create a first pending seek.
   base::TimeDelta seek_time_1 = base::TimeDelta::FromSeconds(5);
   EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_1));
-  PipelineStatusCB seek_cb_1 = SeekPipeline(seek_time_1);
+  PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
   base::RunLoop().RunUntilIdle();
   Mock::VerifyAndClear(&demuxer_);
 
@@ -366,15 +379,15 @@
 
   // When the first seek is completed (or aborted) the second should be issued.
   EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_2));
-  EXPECT_CALL(*pipeline_, Seek(seek_time_2, _));
-  Complete(seek_cb_1);
+  EXPECT_CALL(*pipeline_, OnSeek(seek_time_2, _));
+  Complete(std::move(seek_cb_1));
 }
 
 TEST_F(PipelineControllerTest, PendingSuspend) {
   Complete(StartPipeline());
 
   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
-  PipelineStatusCB seek_cb = SeekPipeline(seek_time);
+  PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
   base::RunLoop().RunUntilIdle();
 
   // While the seek is ongoing, request a suspend.
@@ -383,8 +396,8 @@
   base::RunLoop().RunUntilIdle();
 
   // Expect the suspend to trigger when the seek is completed.
-  EXPECT_CALL(*pipeline_, Suspend(_));
-  Complete(seek_cb);
+  EXPECT_CALL(*pipeline_, OnSuspend(_));
+  Complete(std::move(seek_cb));
 }
 
 TEST_F(PipelineControllerTest, SeekMergesWithResume) {
@@ -412,7 +425,7 @@
   Complete(StartPipeline());
 
   base::TimeDelta seek_time_1 = base::TimeDelta::FromSeconds(5);
-  PipelineStatusCB seek_cb_1 = SeekPipeline(seek_time_1);
+  PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
   base::RunLoop().RunUntilIdle();
 
   // Request another seek while the first is ongoing.
@@ -426,15 +439,15 @@
   base::RunLoop().RunUntilIdle();
 
   // Expect the third seek to trigger when the first seek completes.
-  EXPECT_CALL(*pipeline_, Seek(seek_time_3, _));
-  Complete(seek_cb_1);
+  EXPECT_CALL(*pipeline_, OnSeek(seek_time_3, _));
+  Complete(std::move(seek_cb_1));
 }
 
 TEST_F(PipelineControllerTest, SeekToSeekTimeElided) {
   Complete(StartPipeline());
 
   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
-  PipelineStatusCB seek_cb_1 = SeekPipeline(seek_time);
+  PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
   base::RunLoop().RunUntilIdle();
 
   // Request a seek to the same time again.
@@ -443,7 +456,7 @@
 
   // Complete the first seek.
   // It would be a mock error if the second seek was dispatched here.
-  Complete(seek_cb_1);
+  Complete(std::move(seek_cb_1));
   EXPECT_TRUE(pipeline_controller_.IsStable());
 }
 
@@ -451,7 +464,7 @@
   Complete(StartPipeline_WithDynamicData());
 
   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
-  PipelineStatusCB seek_cb_1 = SeekPipeline(seek_time);
+  PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
   base::RunLoop().RunUntilIdle();
 
   // Request a seek to the same time again.
@@ -459,13 +472,13 @@
   base::RunLoop().RunUntilIdle();
 
   // Expect the second seek to trigger when the first seek completes.
-  EXPECT_CALL(*pipeline_, Seek(seek_time, _));
-  Complete(seek_cb_1);
+  EXPECT_CALL(*pipeline_, OnSeek(seek_time, _));
+  Complete(std::move(seek_cb_1));
 }
 
 TEST_F(PipelineControllerTest, VideoTrackChangeWhileSuspending) {
   Complete(StartPipeline());
-  EXPECT_CALL(*pipeline_, Suspend(_));
+  EXPECT_CALL(*pipeline_, OnSuspend(_));
   EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _)).Times(0);
   pipeline_controller_.Suspend();
   pipeline_controller_.OnSelectedVideoTrackChanged({});
@@ -473,7 +486,7 @@
 
 TEST_F(PipelineControllerTest, AudioTrackChangeWhileSuspending) {
   Complete(StartPipeline());
-  EXPECT_CALL(*pipeline_, Suspend(_));
+  EXPECT_CALL(*pipeline_, OnSuspend(_));
   EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _)).Times(0);
   pipeline_controller_.Suspend();
   pipeline_controller_.OnEnabledAudioTracksChanged({});
@@ -502,7 +515,7 @@
   pipeline_controller_.Suspend();
 
   base::RunLoop loop;
-  EXPECT_CALL(*pipeline_, Suspend(_))
+  EXPECT_CALL(*pipeline_, OnSuspend(_))
       .WillOnce(RunOnceClosure(loop.QuitClosure()));
 
   pipeline_controller_.FireOnTrackChangeCompleteForTesting(
@@ -521,7 +534,7 @@
   pipeline_controller_.Suspend();
 
   base::RunLoop loop;
-  EXPECT_CALL(*pipeline_, Suspend(_))
+  EXPECT_CALL(*pipeline_, OnSuspend(_))
       .WillOnce(RunOnceClosure(loop.QuitClosure()));
 
   pipeline_controller_.FireOnTrackChangeCompleteForTesting(
diff --git a/media/fuchsia/audio/fuchsia_audio_renderer.cc b/media/fuchsia/audio/fuchsia_audio_renderer.cc
index e665b1b..378301ac 100644
--- a/media/fuchsia/audio/fuchsia_audio_renderer.cc
+++ b/media/fuchsia/audio/fuchsia_audio_renderer.cc
@@ -98,7 +98,7 @@
 void FuchsiaAudioRenderer::Initialize(DemuxerStream* stream,
                                       CdmContext* cdm_context,
                                       RendererClient* client,
-                                      const PipelineStatusCB& init_cb) {
+                                      PipelineStatusCallback init_cb) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!demuxer_stream_);
 
@@ -547,4 +547,4 @@
                           media_delta_ / reference_delta_;
 }
 
-}  // namespace media
\ No newline at end of file
+}  // namespace media
diff --git a/media/fuchsia/audio/fuchsia_audio_renderer.h b/media/fuchsia/audio/fuchsia_audio_renderer.h
index ac100b42..a4e6f90 100644
--- a/media/fuchsia/audio/fuchsia_audio_renderer.h
+++ b/media/fuchsia/audio/fuchsia_audio_renderer.h
@@ -37,7 +37,7 @@
   void Initialize(DemuxerStream* stream,
                   CdmContext* cdm_context,
                   RendererClient* client,
-                  const PipelineStatusCB& init_cb) final;
+                  PipelineStatusCallback init_cb) final;
   TimeSource* GetTimeSource() final;
   void Flush(base::OnceClosure callback) final;
   void StartPlaying() final;
@@ -121,7 +121,7 @@
   RendererClient* client_ = nullptr;
 
   // Initialize() completion callback.
-  PipelineStatusCB init_cb_;
+  PipelineStatusCallback init_cb_;
 
   std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
 
@@ -157,4 +157,4 @@
 
 }  // namespace media
 
-#endif  // MEDIA_FUCHSIA_AUDIO_FUCHSIA_AUDIO_RENDERER_H_
\ No newline at end of file
+#endif  // MEDIA_FUCHSIA_AUDIO_FUCHSIA_AUDIO_RENDERER_H_
diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
index 2b747ba..33f55bf 100644
--- a/media/gpu/v4l2/generic_v4l2_device.cc
+++ b/media/gpu/v4l2/generic_v4l2_device.cc
@@ -30,6 +30,7 @@
 #include "media/gpu/macros.h"
 #include "media/gpu/v4l2/generic_v4l2_device.h"
 #include "ui/gfx/native_pixmap.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/egl_util.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image_native_pixmap.h"
@@ -195,7 +196,7 @@
   return dmabuf_fds;
 }
 
-bool GenericV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) {
+bool GenericV4L2Device::CanCreateEGLImageFrom(const Fourcc fourcc) {
   static uint32_t kEGLImageDrmFmtsSupported[] = {
     DRM_FORMAT_ARGB8888,
 #if defined(ARCH_CPU_ARM_FAMILY)
@@ -207,40 +208,28 @@
   return std::find(
              kEGLImageDrmFmtsSupported,
              kEGLImageDrmFmtsSupported + base::size(kEGLImageDrmFmtsSupported),
-             V4L2PixFmtToDrmFormat(v4l2_pixfmt)) !=
+             V4L2PixFmtToDrmFormat(fourcc.ToV4L2PixFmt())) !=
          kEGLImageDrmFmtsSupported + base::size(kEGLImageDrmFmtsSupported);
 }
 
-EGLImageKHR GenericV4L2Device::CreateEGLImage(
-    EGLDisplay egl_display,
-    EGLContext /* egl_context */,
-    GLuint texture_id,
-    const gfx::Size& size,
-    unsigned int buffer_index,
-    uint32_t v4l2_pixfmt,
-    const std::vector<base::ScopedFD>& dmabuf_fds) {
+EGLImageKHR GenericV4L2Device::CreateEGLImage(EGLDisplay egl_display,
+                                              EGLContext /* egl_context */,
+                                              GLuint texture_id,
+                                              const gfx::Size& size,
+                                              unsigned int buffer_index,
+                                              const Fourcc fourcc,
+                                              gfx::NativePixmapHandle handle) {
   DVLOGF(3);
-  if (!CanCreateEGLImageFrom(v4l2_pixfmt)) {
+
+  if (!CanCreateEGLImageFrom(fourcc)) {
     VLOGF(1) << "Unsupported V4L2 pixel format";
     return EGL_NO_IMAGE_KHR;
   }
 
-  const auto vf_format_fourcc = Fourcc::FromV4L2PixFmt(v4l2_pixfmt);
-  if (!vf_format_fourcc) {
-    VLOGF(1) << "Unrecognized pixel format " << FourccToString(v4l2_pixfmt);
-    return EGL_NO_IMAGE_KHR;
-  }
-  const VideoPixelFormat vf_format = vf_format_fourcc->ToVideoPixelFormat();
   // Number of components, as opposed to the number of V4L2 planes, which is
   // just a buffer count.
-  size_t num_planes = VideoFrame::NumPlanes(vf_format);
+  const size_t num_planes = handle.planes.size();
   DCHECK_LE(num_planes, 3u);
-  if (num_planes < dmabuf_fds.size()) {
-    // It's possible for more than one DRM plane to reside in one V4L2 plane,
-    // but not the other way around. We must use all V4L2 planes.
-    LOG(ERROR) << "Invalid plane count";
-    return EGL_NO_IMAGE_KHR;
-  }
 
   std::vector<EGLint> attrs;
   attrs.push_back(EGL_WIDTH);
@@ -248,30 +237,15 @@
   attrs.push_back(EGL_HEIGHT);
   attrs.push_back(size.height());
   attrs.push_back(EGL_LINUX_DRM_FOURCC_EXT);
-  attrs.push_back(V4L2PixFmtToDrmFormat(v4l2_pixfmt));
+  attrs.push_back(V4L2PixFmtToDrmFormat(fourcc.ToV4L2PixFmt()));
 
-  // For existing formats, if we have less buffers (V4L2 planes) than
-  // components (planes), the remaining planes are stored in the last
-  // V4L2 plane. Use one V4L2 plane per each component until we run out of V4L2
-  // planes, and use the last V4L2 plane for all remaining components, each
-  // with an offset equal to the size of the preceding planes in the same
-  // V4L2 plane.
-  size_t v4l2_plane = 0;
-  size_t plane_offset = 0;
   for (size_t plane = 0; plane < num_planes; ++plane) {
     attrs.push_back(EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3);
-    attrs.push_back(dmabuf_fds[v4l2_plane].get());
+    attrs.push_back(handle.planes[plane].fd.get());
     attrs.push_back(EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3);
-    attrs.push_back(plane_offset);
+    attrs.push_back(handle.planes[plane].offset);
     attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3);
-    attrs.push_back(VideoFrame::RowBytes(plane, vf_format, size.width()));
-
-    if (v4l2_plane + 1 < dmabuf_fds.size()) {
-      ++v4l2_plane;
-      plane_offset = 0;
-    } else {
-      plane_offset += VideoFrame::PlaneSize(vf_format, plane, size).GetArea();
-    }
+    attrs.push_back(handle.planes[plane].stride);
   }
 
   attrs.push_back(EGL_NONE);
@@ -290,61 +264,24 @@
 
 scoped_refptr<gl::GLImage> GenericV4L2Device::CreateGLImage(
     const gfx::Size& size,
-    uint32_t fourcc,
-    const std::vector<base::ScopedFD>& dmabuf_fds) {
+    const Fourcc fourcc,
+    gfx::NativePixmapHandle handle) {
   DVLOGF(3);
   DCHECK(CanCreateEGLImageFrom(fourcc));
-  const auto vf_format_fourcc = Fourcc::FromV4L2PixFmt(fourcc);
-  if (!vf_format_fourcc) {
-    VLOGF(1) << "Unrecognized pixel format " << FourccToString(fourcc);
-    return nullptr;
-  }
-  const VideoPixelFormat vf_format = vf_format_fourcc->ToVideoPixelFormat();
-  size_t num_planes = VideoFrame::NumPlanes(vf_format);
+
+  size_t num_planes = handle.planes.size();
   DCHECK_LE(num_planes, 3u);
-  DCHECK_LE(dmabuf_fds.size(), num_planes);
 
   gfx::NativePixmapHandle native_pixmap_handle;
 
-  std::vector<base::ScopedFD> duped_fds;
-  // The number of file descriptors can be less than the number of planes when
-  // v4l2 pix fmt, |fourcc|, is a single plane format. Duplicating the last
-  // file descriptor should be safely used for the later planes, because they
-  // are on the last buffer.
-  for (size_t i = 0; i < num_planes; ++i) {
-    int fd =
-        i < dmabuf_fds.size() ? dmabuf_fds[i].get() : dmabuf_fds.back().get();
-    duped_fds.emplace_back(HANDLE_EINTR(dup(fd)));
-    if (!duped_fds.back().is_valid()) {
-      VPLOGF(1) << "Failed duplicating a dmabuf fd";
-      return nullptr;
-    }
-  }
-
-  // For existing formats, if we have less buffers (V4L2 planes) than
-  // components (planes), the remaining planes are stored in the last
-  // V4L2 plane. Use one V4L2 plane per each component until we run out of V4L2
-  // planes, and use the last V4L2 plane for all remaining components, each
-  // with an offset equal to the size of the preceding planes in the same
-  // V4L2 plane.
-  size_t v4l2_plane = 0;
-  size_t plane_offset = 0;
   for (size_t p = 0; p < num_planes; ++p) {
     native_pixmap_handle.planes.emplace_back(
-        VideoFrame::RowBytes(p, vf_format, size.width()), plane_offset,
-        VideoFrame::PlaneSize(vf_format, p, size).GetArea(),
-        std::move(duped_fds[p]));
-
-    if (v4l2_plane + 1 < dmabuf_fds.size()) {
-      ++v4l2_plane;
-      plane_offset = 0;
-    } else {
-      plane_offset += VideoFrame::PlaneSize(vf_format, p, size).GetArea();
-    }
+        handle.planes[p].stride, handle.planes[p].offset, handle.planes[p].size,
+        std::move(handle.planes[p].fd));
   }
 
   gfx::BufferFormat buffer_format = gfx::BufferFormat::BGRA_8888;
-  switch (fourcc) {
+  switch (fourcc.ToV4L2PixFmt()) {
     case DRM_FORMAT_ARGB8888:
       buffer_format = gfx::BufferFormat::BGRA_8888;
       break;
diff --git a/media/gpu/v4l2/generic_v4l2_device.h b/media/gpu/v4l2/generic_v4l2_device.h
index ba52f69..4e98edfc 100644
--- a/media/gpu/v4l2/generic_v4l2_device.h
+++ b/media/gpu/v4l2/generic_v4l2_device.h
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "media/gpu/buildflags.h"
 #include "media/gpu/v4l2/v4l2_device.h"
+#include "ui/gfx/native_pixmap_handle.h"
 
 namespace media {
 
@@ -43,20 +44,19 @@
       size_t num_planes,
       enum v4l2_buf_type buf_type) override;
 
-  bool CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) override;
-  EGLImageKHR CreateEGLImage(
-      EGLDisplay egl_display,
-      EGLContext egl_context,
-      GLuint texture_id,
-      const gfx::Size& size,
-      unsigned int buffer_index,
-      uint32_t v4l2_pixfmt,
-      const std::vector<base::ScopedFD>& dmabuf_fds) override;
+  bool CanCreateEGLImageFrom(const Fourcc fourcc) override;
+  EGLImageKHR CreateEGLImage(EGLDisplay egl_display,
+                             EGLContext egl_context,
+                             GLuint texture_id,
+                             const gfx::Size& size,
+                             unsigned int buffer_index,
+                             const Fourcc fourcc,
+                             gfx::NativePixmapHandle handle) override;
 
   scoped_refptr<gl::GLImage> CreateGLImage(
       const gfx::Size& size,
-      uint32_t fourcc,
-      const std::vector<base::ScopedFD>& dmabuf_fds) override;
+      const Fourcc fourcc,
+      gfx::NativePixmapHandle handle) override;
 
   EGLBoolean DestroyEGLImage(EGLDisplay egl_display,
                              EGLImageKHR egl_image) override;
diff --git a/media/gpu/v4l2/tegra_v4l2_device.cc b/media/gpu/v4l2/tegra_v4l2_device.cc
index 175d3da..f38c32d0 100644
--- a/media/gpu/v4l2/tegra_v4l2_device.cc
+++ b/media/gpu/v4l2/tegra_v4l2_device.cc
@@ -10,6 +10,7 @@
 #include "base/trace_event/trace_event.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/v4l2/tegra_v4l2_device.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace media {
@@ -216,8 +217,8 @@
   return dmabuf_fds;
 }
 
-bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) {
-  return v4l2_pixfmt == V4L2_PIX_FMT_NV12M;
+bool TegraV4L2Device::CanCreateEGLImageFrom(const Fourcc fourcc) {
+  return fourcc.ToV4L2PixFmt() == V4L2_PIX_FMT_NV12M;
 }
 
 EGLImageKHR TegraV4L2Device::CreateEGLImage(
@@ -226,10 +227,11 @@
     GLuint texture_id,
     const gfx::Size& /* size */,
     unsigned int buffer_index,
-    uint32_t v4l2_pixfmt,
-    const std::vector<base::ScopedFD>& /* dmabuf_fds */) {
+    const Fourcc fourcc,
+    gfx::NativePixmapHandle /* handle */) {
   DVLOGF(3);
-  if (!CanCreateEGLImageFrom(v4l2_pixfmt)) {
+
+  if (!CanCreateEGLImageFrom(fourcc)) {
     LOG(ERROR) << "Unsupported V4L2 pixel format";
     return EGL_NO_IMAGE_KHR;
   }
@@ -251,8 +253,8 @@
 }
 scoped_refptr<gl::GLImage> TegraV4L2Device::CreateGLImage(
     const gfx::Size& size,
-    uint32_t fourcc,
-    const std::vector<base::ScopedFD>& dmabuf_fds) {
+    const Fourcc fourcc,
+    gfx::NativePixmapHandle /* handle */) {
   NOTREACHED();
   return nullptr;
 }
diff --git a/media/gpu/v4l2/tegra_v4l2_device.h b/media/gpu/v4l2/tegra_v4l2_device.h
index 763f099..ed1cffa7 100644
--- a/media/gpu/v4l2/tegra_v4l2_device.h
+++ b/media/gpu/v4l2/tegra_v4l2_device.h
@@ -16,6 +16,7 @@
 
 #include "base/macros.h"
 #include "media/gpu/v4l2/v4l2_device.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace media {
@@ -43,19 +44,18 @@
       int index,
       size_t num_planes,
       enum v4l2_buf_type buf_type) override;
-  bool CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) override;
-  EGLImageKHR CreateEGLImage(
-      EGLDisplay egl_display,
-      EGLContext egl_context,
-      GLuint texture_id,
-      const gfx::Size& size,
-      unsigned int buffer_index,
-      uint32_t v4l2_pixfmt,
-      const std::vector<base::ScopedFD>& dmabuf_fds) override;
+  bool CanCreateEGLImageFrom(const Fourcc fourcc) override;
+  EGLImageKHR CreateEGLImage(EGLDisplay egl_display,
+                             EGLContext egl_context,
+                             GLuint texture_id,
+                             const gfx::Size& size,
+                             unsigned int buffer_index,
+                             const Fourcc fourcc,
+                             gfx::NativePixmapHandle handle) override;
   scoped_refptr<gl::GLImage> CreateGLImage(
       const gfx::Size& size,
-      uint32_t fourcc,
-      const std::vector<base::ScopedFD>& dmabuf_fds) override;
+      const Fourcc fourcc,
+      gfx::NativePixmapHandle handle) override;
   EGLBoolean DestroyEGLImage(EGLDisplay egl_display,
                              EGLImageKHR egl_image) override;
   GLenum GetTextureTarget() override;
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h
index 64438ac..9ddfb8d 100644
--- a/media/gpu/v4l2/v4l2_device.h
+++ b/media/gpu/v4l2/v4l2_device.h
@@ -26,11 +26,13 @@
 #include "media/base/video_decoder_config.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_layout.h"
+#include "media/gpu/chromeos/fourcc.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/gpu/v4l2/v4l2_device_poller.h"
 #include "media/video/video_decode_accelerator.h"
 #include "media/video/video_encode_accelerator.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image.h"
 
@@ -593,33 +595,25 @@
 
   // Return true if the given V4L2 pixfmt can be used in CreateEGLImage()
   // for the current platform.
-  virtual bool CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) = 0;
+  virtual bool CanCreateEGLImageFrom(const Fourcc fourcc) = 0;
 
-  // Create an EGLImage from provided |dmabuf_fds| and bind |texture_id| to it.
+  // Create an EGLImage from provided |handle|, taking full ownership of it.
   // Some implementations may also require the V4L2 |buffer_index| of the buffer
-  // for which |dmabuf_fds| have been exported.
-  // The caller may choose to close the file descriptors after this method
-  // returns, and may expect the buffers to remain valid for the lifetime of
-  // the created EGLImage.
+  // for which |handle| has been exported.
   // Return EGL_NO_IMAGE_KHR on failure.
-  virtual EGLImageKHR CreateEGLImage(
-      EGLDisplay egl_display,
-      EGLContext egl_context,
-      GLuint texture_id,
-      const gfx::Size& size,
-      unsigned int buffer_index,
-      uint32_t v4l2_pixfmt,
-      const std::vector<base::ScopedFD>& dmabuf_fds) = 0;
+  virtual EGLImageKHR CreateEGLImage(EGLDisplay egl_display,
+                                     EGLContext egl_context,
+                                     GLuint texture_id,
+                                     const gfx::Size& size,
+                                     unsigned int buffer_index,
+                                     const Fourcc fourcc,
+                                     gfx::NativePixmapHandle handle) = 0;
 
-  // Create a GLImage from provided |dmabuf_fds|.
-  // The caller may choose to close the file descriptors after this method
-  // returns, and may expect the buffers to remain valid for the lifetime of
-  // the created GLImage.
-  // Return the newly created GLImage.
+  // Create a GLImage from provided |handle|, taking full ownership of it.
   virtual scoped_refptr<gl::GLImage> CreateGLImage(
       const gfx::Size& size,
-      uint32_t fourcc,
-      const std::vector<base::ScopedFD>& dmabuf_fds) = 0;
+      const Fourcc fourcc,
+      gfx::NativePixmapHandle handle) = 0;
 
   // Destroys the EGLImageKHR.
   virtual EGLBoolean DestroyEGLImage(EGLDisplay egl_display,
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
index ed8880a..0c7f768a 100644
--- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -37,6 +37,7 @@
 #include "media/base/unaligned_shared_memory.h"
 #include "media/base/video_types.h"
 #include "media/gpu/chromeos/fourcc.h"
+#include "media/gpu/chromeos/platform_video_frame_utils.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/v4l2/v4l2_decode_surface.h"
 #include "media/gpu/v4l2/v4l2_h264_accelerator.h"
@@ -46,6 +47,7 @@
 #include "media/gpu/v4l2/v4l2_vp8_accelerator.h"
 #include "media/gpu/v4l2/v4l2_vp8_accelerator_legacy.h"
 #include "media/gpu/v4l2/v4l2_vp9_accelerator.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image.h"
 #include "ui/gl/scoped_binders.h"
@@ -143,8 +145,7 @@
     EGLDisplay egl_display,
     const BindGLImageCallback& bind_image_cb,
     const MakeGLContextCurrentCallback& make_context_current_cb)
-    : input_planes_count_(0),
-      output_planes_count_(0),
+    : output_planes_count_(0),
       child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       device_(std::move(device)),
       decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"),
@@ -241,8 +242,6 @@
 
   video_profile_ = config.profile;
 
-  input_planes_count_ = 1;
-
   input_format_fourcc_ =
       V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_, true);
 
@@ -484,7 +483,7 @@
   format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   format.fmt.pix_mp.pixelformat = input_format_fourcc_;
   format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size;
-  format.fmt.pix_mp.num_planes = input_planes_count_;
+  format.fmt.pix_mp.num_planes = 1;
   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
   DCHECK_EQ(format.fmt.pix_mp.pixelformat, input_format_fourcc_);
 
@@ -494,9 +493,13 @@
   memset(&fmtdesc, 0, sizeof(fmtdesc));
   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   output_format_fourcc_ = base::nullopt;
+  output_planes_count_ = 0;
   while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
-    if (device_->CanCreateEGLImageFrom(fmtdesc.pixelformat)) {
-      output_format_fourcc_ = Fourcc::FromV4L2PixFmt(fmtdesc.pixelformat);
+    auto fourcc = Fourcc::FromV4L2PixFmt(fmtdesc.pixelformat);
+    if (fourcc && device_->CanCreateEGLImageFrom(*fourcc)) {
+      output_format_fourcc_ = fourcc;
+      output_planes_count_ = V4L2Device::GetNumPlanesOfV4L2PixFmt(
+        output_format_fourcc_->ToV4L2PixFmt());
       break;
     }
     ++fmtdesc.index;
@@ -520,6 +523,9 @@
       VLOGF(1) << "Can't find a usable input format from image processor";
       return false;
     }
+    output_planes_count_ = V4L2Device::GetNumPlanesOfV4L2PixFmt(
+        output_format_fourcc_->ToV4L2PixFmt());
+
     gl_image_format_fourcc_ = v4l2_vda_helpers::FindImageProcessorOutputFormat(
         image_processor_device_.get());
     if (!gl_image_format_fourcc_) {
@@ -528,14 +534,10 @@
     }
     gl_image_planes_count_ = V4L2Device::GetNumPlanesOfV4L2PixFmt(
         gl_image_format_fourcc_->ToV4L2PixFmt());
-    output_planes_count_ = V4L2Device::GetNumPlanesOfV4L2PixFmt(
-        output_format_fourcc_->ToV4L2PixFmt());
     gl_image_device_ = image_processor_device_;
   } else {
     gl_image_format_fourcc_ = output_format_fourcc_;
-    output_planes_count_ = gl_image_planes_count_ =
-        V4L2Device::GetNumPlanesOfV4L2PixFmt(
-            output_format_fourcc_->ToV4L2PixFmt());
+    gl_image_planes_count_ = output_planes_count_;
     gl_image_device_ = device_;
   }
 
@@ -948,12 +950,10 @@
     case V4L2_MEMORY_MMAP:
       ret = std::move(output_buffer).QueueMMap();
       break;
-    case V4L2_MEMORY_DMABUF: {
-      const auto& fds = output_record.output_frame->DmabufFds();
-      DCHECK_EQ(output_planes_count_, fds.size());
-      ret = std::move(output_buffer).QueueDMABuf(fds);
+    case V4L2_MEMORY_DMABUF:
+      ret = std::move(output_buffer)
+                .QueueDMABuf(output_record.output_frame->DmabufFds());
       break;
-    }
     default:
       NOTREACHED();
   }
@@ -1387,19 +1387,14 @@
   }
 
   // Reserve all buffers until ImportBufferForPictureTask() is called
-  while (auto buffer_opt = output_queue_->GetFreeBuffer()) {
-    V4L2WritableBufferRef buffer(std::move(*buffer_opt));
-    int i = buffer.BufferId();
+  std::vector<V4L2WritableBufferRef> v4l2_buffers;
+  while (auto buffer_opt = output_queue_->GetFreeBuffer())
+    v4l2_buffers.push_back(std::move(*buffer_opt));
 
-    DCHECK_EQ(output_wait_map_.count(buffers[i].id()), 0u);
-    // The buffer will remain here until ImportBufferForPicture is called,
-    // either by the client, or by ourselves, if we are allocating.
-    output_wait_map_.emplace(buffers[i].id(), std::move(buffer));
-  }
-  // All available buffers should be in the wait map now.
-  DCHECK_EQ(output_buffer_map_.size(), output_wait_map_.size());
+  // Now setup the output record for each buffer and import it if needed.
+  for (auto&& buffer : v4l2_buffers) {
+    const int i = buffer.BufferId();
 
-  for (size_t i = 0; i < buffers.size(); i++) {
     OutputRecord& output_record = output_buffer_map_[i];
     DCHECK_EQ(output_record.picture_id, -1);
     DCHECK_EQ(output_record.cleared, false);
@@ -1413,30 +1408,36 @@
                                           ? 0
                                           : buffers[i].client_texture_ids()[0];
 
+    // We move the buffer into output_wait_map_, so get a reference to
+    // its video frame if we need it to create the native pixmap for import.
+    scoped_refptr<VideoFrame> video_frame;
+    if (output_mode_ == Config::OutputMode::ALLOCATE &&
+        !image_processor_device_) {
+      video_frame = buffer.GetVideoFrame();
+    }
+
+    // The buffer will remain here until ImportBufferForPicture is called,
+    // either by the client, or by ourselves, if we are allocating.
+    DCHECK_EQ(output_wait_map_.count(buffers[i].id()), 0u);
+    output_wait_map_.emplace(buffers[i].id(), std::move(buffer));
+
     // If we are in allocate mode, then we can already call
     // ImportBufferForPictureTask().
     if (output_mode_ == Config::OutputMode::ALLOCATE) {
-      std::vector<base::ScopedFD> passed_dmabuf_fds;
+      gfx::NativePixmapHandle native_pixmap;
 
       // If we are using an image processor, the DMABufs that we need to import
       // are those of the image processor's buffers, not the decoders. So
-      // pass an empty FDs array in that case.
-
-      if (!image_processor_) {
-        passed_dmabuf_fds = gl_image_device_->GetDmabufsForV4L2Buffer(
-            i, gl_image_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-        if (passed_dmabuf_fds.empty()) {
-          NOTIFY_ERROR(PLATFORM_FAILURE);
-          return;
-        }
+      // pass an empty native pixmap in that case.
+      if (!image_processor_device_) {
+        native_pixmap =
+            CreateGpuMemoryBufferHandle(video_frame.get()).native_pixmap_handle;
       }
 
-      int plane_horiz_bits_per_pixel = VideoFrame::PlaneHorizontalBitsPerPixel(
-          gl_image_format_fourcc_->ToVideoPixelFormat(), 0);
-      ImportBufferForPictureTask(
-          output_record.picture_id, std::move(passed_dmabuf_fds),
-          gl_image_size_.width() * plane_horiz_bits_per_pixel / 8);
+      ImportBufferForPictureTask(output_record.picture_id,
+                                 std::move(native_pixmap));
     }  // else we'll get triggered via ImportBufferForPicture() from client.
+
     DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
   }
 
@@ -1449,7 +1450,7 @@
 void V4L2SliceVideoDecodeAccelerator::CreateGLImageFor(
     size_t buffer_index,
     int32_t picture_buffer_id,
-    std::vector<base::ScopedFD> passed_dmabuf_fds,
+    gfx::NativePixmapHandle handle,
     GLuint client_texture_id,
     GLuint texture_id,
     const gfx::Size& size,
@@ -1471,8 +1472,8 @@
     return;
   }
 
-  scoped_refptr<gl::GLImage> gl_image = gl_image_device_->CreateGLImage(
-      size, fourcc.ToV4L2PixFmt(), passed_dmabuf_fds);
+  scoped_refptr<gl::GLImage> gl_image =
+      gl_image_device_->CreateGLImage(size, fourcc, std::move(handle));
   if (!gl_image) {
     VLOGF(1) << "Could not create GLImage,"
              << " index=" << buffer_index << " texture_id=" << texture_id;
@@ -1521,38 +1522,12 @@
     return;
   }
 
-  std::vector<base::ScopedFD> dmabuf_fds;
-  for (auto& plane : handle.planes) {
-    dmabuf_fds.push_back(std::move(plane.fd));
-  }
-
-  // If the driver does not accept as many fds as we received from the client,
-  // we have to check if the additional fds are actually duplicated fds pointing
-  // to previous planes; if so, we can close the duplicates and keep only the
-  // original fd(s).
-  // Assume that an fd is a duplicate of a previous plane's fd if offset != 0.
-  // Otherwise, if offset == 0, return error as it may be pointing to a new
-  // plane.
-  while (dmabuf_fds.size() > gl_image_planes_count_) {
-    const size_t idx = dmabuf_fds.size() - 1;
-    if (handle.planes[idx].offset == 0) {
-      VLOGF(1) << "The dmabuf fd points to a new buffer, ";
-      NOTIFY_ERROR(INVALID_ARGUMENT);
-      return;
-    }
-    // Drop safely, because this fd is duplicate dmabuf fd pointing to previous
-    // buffer and the appropriate address can be accessed by associated offset.
-    dmabuf_fds.pop_back();
-  }
-
-  ImportBufferForPictureTask(picture_buffer_id, std::move(dmabuf_fds),
-                             handle.planes[0].stride);
+  ImportBufferForPictureTask(picture_buffer_id, std::move(handle));
 }
 
 void V4L2SliceVideoDecodeAccelerator::ImportBufferForPictureTask(
     int32_t picture_buffer_id,
-    std::vector<base::ScopedFD> passed_dmabuf_fds,
-    int32_t stride) {
+    gfx::NativePixmapHandle handle) {
   DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
 
@@ -1583,30 +1558,34 @@
   // TODO(crbug.com/982172): This must be done in AssignPictureBuffers().
   // However the size of PictureBuffer might not be adjusted by ARC++. So we
   // keep this until ARC++ side is fixed.
-  int plane_horiz_bits_per_pixel = VideoFrame::PlaneHorizontalBitsPerPixel(
-      gl_image_format_fourcc_->ToVideoPixelFormat(), 0);
-  if (plane_horiz_bits_per_pixel == 0 ||
-      (stride * 8) % plane_horiz_bits_per_pixel != 0) {
-    VLOGF(1) << "Invalid format " << gl_image_format_fourcc_->ToString()
-             << " or stride " << stride;
-    NOTIFY_ERROR(INVALID_ARGUMENT);
-    return;
-  }
-  int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel;
-  if (image_processor_device_ && !image_processor_) {
-    DCHECK_EQ(kAwaitingPictureBuffers, state_);
-    // This is the first buffer import. Create the image processor and change
-    // the decoder state. The client may adjust the coded width. We don't have
-    // the final coded size in AssignPictureBuffers yet. Use the adjusted coded
-    // width to create the image processor.
-    DVLOGF(3) << "Original gl_image_size=" << gl_image_size_.ToString()
-              << ", adjusted coded width=" << adjusted_coded_width;
-    DCHECK_GE(adjusted_coded_width, gl_image_size_.width());
-    gl_image_size_.set_width(adjusted_coded_width);
-    if (!CreateImageProcessor())
+  if (output_mode_ == Config::OutputMode::IMPORT) {
+    const int32_t stride = handle.planes[0].stride;
+    const int plane_horiz_bits_per_pixel =
+        VideoFrame::PlaneHorizontalBitsPerPixel(
+            gl_image_format_fourcc_->ToVideoPixelFormat(), 0);
+    if (plane_horiz_bits_per_pixel == 0 ||
+        (stride * 8) % plane_horiz_bits_per_pixel != 0) {
+      VLOGF(1) << "Invalid format " << gl_image_format_fourcc_->ToString()
+               << " or stride " << stride;
+      NOTIFY_ERROR(INVALID_ARGUMENT);
       return;
+    }
+    int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel;
+    if (image_processor_device_ && !image_processor_) {
+      DCHECK_EQ(kAwaitingPictureBuffers, state_);
+      // This is the first buffer import. Create the image processor and change
+      // the decoder state. The client may adjust the coded width. We don't have
+      // the final coded size in AssignPictureBuffers yet. Use the adjusted
+      // coded width to create the image processor.
+      DVLOGF(3) << "Original gl_image_size=" << gl_image_size_.ToString()
+                << ", adjusted coded width=" << adjusted_coded_width;
+      DCHECK_GE(adjusted_coded_width, gl_image_size_.width());
+      gl_image_size_.set_width(adjusted_coded_width);
+      if (!CreateImageProcessor())
+        return;
+    }
+    DCHECK_EQ(gl_image_size_.width(), adjusted_coded_width);
   }
-  DCHECK_EQ(gl_image_size_.width(), adjusted_coded_width);
 
   // Put us in kIdle to allow further event processing.
   // ProcessPendingEventsIfNeeded() will put us back into kDecoding after all
@@ -1620,14 +1599,22 @@
             base::Unretained(this)));
   }
 
-  // If in import mode, build output_frame from the passed DMABUF FDs.
+  // If we are importing, create the output VideoFrame that we will render
+  // into.
   if (output_mode_ == Config::OutputMode::IMPORT) {
-    DCHECK_EQ(gl_image_planes_count_, passed_dmabuf_fds.size());
+    DCHECK_GT(handle.planes.size(), 0u);
     DCHECK(!iter->output_frame);
 
-    // TODO(acourbot): Create a more accurate layout from the GMBhandle instead
-    // of assuming the image size will be enough (we may have extra information
-    // between planes).
+    // Duplicate the buffer FDs for the VideoFrame instance.
+    std::vector<base::ScopedFD> duped_fds;
+    for (const gfx::NativePixmapPlane& plane : handle.planes) {
+      duped_fds.emplace_back(HANDLE_EINTR(dup(plane.fd.get())));
+      if (!duped_fds.back().is_valid()) {
+        VPLOG(1) << "Failed to duplicate plane FD!";
+        NOTIFY_ERROR(PLATFORM_FAILURE);
+        return;
+      }
+    }
     auto layout = VideoFrameLayout::Create(
         gl_image_format_fourcc_->ToVideoPixelFormat(), gl_image_size_);
     if (!layout) {
@@ -1637,24 +1624,23 @@
     }
     const gfx::Rect visible_rect = decoder_->GetVisibleRect();
     iter->output_frame = VideoFrame::WrapExternalDmabufs(
-        *layout, visible_rect, visible_rect.size(),
-        DuplicateFDs(passed_dmabuf_fds), base::TimeDelta());
+        *layout, visible_rect, visible_rect.size(), std::move(duped_fds),
+        base::TimeDelta());
   }
 
   // We should only create the GL image if rendering is enabled
   // (texture_id !=0). Moreover, if an image processor is in use, we will
   // create the GL image when its buffer becomes visible in FrameProcessed().
   if (iter->texture_id != 0 && !image_processor_) {
-    DCHECK_EQ(gl_image_planes_count_, passed_dmabuf_fds.size());
+    DCHECK_GT(handle.planes.size(), 0u);
     size_t index = iter - output_buffer_map_.begin();
 
     child_task_runner_->PostTask(
         FROM_HERE,
         base::BindOnce(&V4L2SliceVideoDecodeAccelerator::CreateGLImageFor,
-                       weak_this_, index, picture_buffer_id,
-                       std::move(passed_dmabuf_fds), iter->client_texture_id,
-                       iter->texture_id, gl_image_size_,
-                       *gl_image_format_fourcc_));
+                       weak_this_, index, picture_buffer_id, std::move(handle),
+                       iter->client_texture_id, iter->texture_id,
+                       gl_image_size_, *gl_image_format_fourcc_));
   }
 
   // Buffer is now ready to be used.
@@ -2304,12 +2290,12 @@
     DCHECK(frame->HasDmaBufs());
     child_task_runner_->PostTask(
         FROM_HERE,
-        base::BindOnce(&V4L2SliceVideoDecodeAccelerator::CreateGLImageFor,
-                       weak_this_, ip_buffer_index, ip_output_record.picture_id,
-                       media::DuplicateFDs(frame->DmabufFds()),
-                       ip_output_record.client_texture_id,
-                       ip_output_record.texture_id, gl_image_size_,
-                       *gl_image_format_fourcc_));
+        base::BindOnce(
+            &V4L2SliceVideoDecodeAccelerator::CreateGLImageFor, weak_this_,
+            ip_buffer_index, ip_output_record.picture_id,
+            CreateGpuMemoryBufferHandle(frame.get()).native_pixmap_handle,
+            ip_output_record.client_texture_id, ip_output_record.texture_id,
+            gl_image_size_, *gl_image_format_fourcc_));
   }
 
   DCHECK(!surfaces_at_ip_.empty());
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h
index 33fffb8c..27dc97e49 100644
--- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h
@@ -31,6 +31,7 @@
 #include "media/gpu/vp8_decoder.h"
 #include "media/gpu/vp9_decoder.h"
 #include "media/video/video_decode_accelerator.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_fence_egl.h"
 
 namespace media {
@@ -264,13 +265,11 @@
   // via AssignPictureBuffers() on decoder thread.
   void AssignPictureBuffersTask(const std::vector<PictureBuffer>& buffers);
 
-  // Use buffer backed by dmabuf file descriptors in |passed_dmabuf_fds| for the
-  // OutputRecord associated with |picture_buffer_id|, taking ownership of the
-  // file descriptors. |stride| is the number of bytes from one row of pixels
-  // to the next row.
+  // Use buffer backed by |handle| for the OutputRecord associated with
+  // |picture_buffer_id|. |handle| does not need to be valid if we are in
+  // ALLOCATE mode and using an image processor.
   void ImportBufferForPictureTask(int32_t picture_buffer_id,
-                                  std::vector<base::ScopedFD> passed_dmabuf_fds,
-                                  int32_t stride);
+                                  gfx::NativePixmapHandle handle);
 
   // Check that |planes| and |dmabuf_fds| are valid in import mode and call
   // ImportBufferForPictureTask.
@@ -280,11 +279,11 @@
 
   // Create a GLImage for the buffer associated with V4L2 |buffer_index| and
   // for |picture_buffer_id|, backed by dmabuf file descriptors in
-  // |passed_dmabuf_fds|, taking ownership of them.
+  // |dmabuf_fds|, taking ownership of them.
   // The GLImage will be associated |client_texture_id| in gles2 decoder.
   void CreateGLImageFor(size_t buffer_index,
                         int32_t picture_buffer_id,
-                        std::vector<base::ScopedFD> passed_dmabuf_fds,
+                        gfx::NativePixmapHandle handle,
                         GLuint client_texture_id,
                         GLuint texture_id,
                         const gfx::Size& size,
@@ -365,7 +364,6 @@
   // VideoCodecProfiles supported by a v4l2 decoder driver.
   std::vector<VideoCodecProfile> supported_profiles_;
 
-  size_t input_planes_count_;
   size_t output_planes_count_;
 
   // GPU Child thread task runner.
diff --git a/media/gpu/v4l2/v4l2_vda_helpers.cc b/media/gpu/v4l2/v4l2_vda_helpers.cc
index 8de8cbd..c4d5ba9 100644
--- a/media/gpu/v4l2/v4l2_vda_helpers.cc
+++ b/media/gpu/v4l2/v4l2_vda_helpers.cc
@@ -53,9 +53,10 @@
             preferred_formats_first);
 
   for (uint32_t processor_output_format : processor_output_formats) {
-    if (ip_device->CanCreateEGLImageFrom(processor_output_format)) {
+    auto fourcc = Fourcc::FromV4L2PixFmt(processor_output_format);
+    if (fourcc && ip_device->CanCreateEGLImageFrom(*fourcc)) {
       DVLOGF(3) << "Image processor output format=" << processor_output_format;
-      return Fourcc::FromV4L2PixFmt(processor_output_format);
+      return fourcc;
     }
   }
 
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
index c77a96d8..9f8f082a 100644
--- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -32,12 +32,14 @@
 #include "media/base/video_frame_layout.h"
 #include "media/base/video_types.h"
 #include "media/gpu/chromeos/fourcc.h"
+#include "media/gpu/chromeos/platform_video_frame_utils.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/v4l2/v4l2_image_processor_backend.h"
 #include "media/gpu/v4l2/v4l2_stateful_workaround.h"
 #include "media/gpu/v4l2/v4l2_vda_helpers.h"
 #include "media/video/h264_parser.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/scoped_binders.h"
 
@@ -144,7 +146,6 @@
       reset_pending_(false),
       decoder_partial_frame_pending_(false),
       output_dpb_size_(0),
-      output_planes_count_(0),
       picture_clearing_count_(0),
       device_poll_thread_("V4L2DevicePollThread"),
       egl_display_(egl_display),
@@ -152,7 +153,6 @@
       make_context_current_cb_(make_context_current_cb),
       video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN),
       input_format_fourcc_(0),
-      egl_image_planes_count_(0),
       weak_this_factory_(this) {
   weak_this_ = weak_this_factory_.GetWeakPtr();
 }
@@ -411,15 +411,14 @@
   }
 
   // Reserve all buffers until ImportBufferForPictureTask() is called
-  while (auto buffer_opt = output_queue_->GetFreeBuffer()) {
-    V4L2WritableBufferRef buffer(std::move(*buffer_opt));
-    int i = buffer.BufferId();
+  std::vector<V4L2WritableBufferRef> v4l2_buffers;
+  while (auto buffer_opt = output_queue_->GetFreeBuffer())
+    v4l2_buffers.push_back(std::move(*buffer_opt));
 
-    DCHECK_EQ(output_wait_map_.count(buffers[i].id()), 0u);
-    output_wait_map_.emplace(buffers[i].id(), std::move(buffer));
-  }
+  // Now setup the output record for each buffer and import it if needed.
+  for (auto&& buffer : v4l2_buffers) {
+    const int i = buffer.BufferId();
 
-  for (size_t i = 0; i < buffers.size(); i++) {
     DCHECK(buffers[i].size() == egl_image_size_);
 
     OutputRecord& output_record = output_buffer_map_[i];
@@ -432,20 +431,30 @@
                                    ? 0
                                    : buffers[i].service_texture_ids()[0];
 
+    // We move the buffer into output_wait_map_, so get a reference to
+    // its video frame if we need it to create the native pixmap for import.
+    scoped_refptr<VideoFrame> video_frame;
+    if (output_mode_ == Config::OutputMode::ALLOCATE &&
+        !image_processor_device_)
+      video_frame = buffer.GetVideoFrame();
+
+    // The buffer will remain here until ImportBufferForPicture is called,
+    // either by the client, or by ourselves, if we are allocating.
+    DCHECK_EQ(output_wait_map_.count(buffers[i].id()), 0u);
+    output_wait_map_.emplace(buffers[i].id(), std::move(buffer));
+
     if (output_mode_ == Config::OutputMode::ALLOCATE) {
-      std::vector<base::ScopedFD> dmabuf_fds;
-      dmabuf_fds = egl_image_device_->GetDmabufsForV4L2Buffer(
-          i, egl_image_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-      if (dmabuf_fds.empty()) {
-        VLOGF(1) << "Failed to get DMABUFs for EGLImage.";
-        NOTIFY_ERROR(PLATFORM_FAILURE);
-        return;
-      }
-      int plane_horiz_bits_per_pixel = VideoFrame::PlaneHorizontalBitsPerPixel(
-          egl_image_format_fourcc_->ToVideoPixelFormat(), 0);
-      ImportBufferForPictureTask(
-          output_record.picture_id, std::move(dmabuf_fds),
-          egl_image_size_.width() * plane_horiz_bits_per_pixel / 8);
+      gfx::NativePixmapHandle native_pixmap;
+
+      // If we are using an image processor, the DMABufs that we need to import
+      // are those of the image processor's buffers, not the decoders. So
+      // pass an empty native pixmap in that case.
+      if (!image_processor_device_)
+        native_pixmap =
+            CreateGpuMemoryBufferHandle(video_frame.get()).native_pixmap_handle;
+
+      ImportBufferForPictureTask(output_record.picture_id,
+                                 std::move(native_pixmap));
     }  // else we'll get triggered via ImportBufferForPicture() from client.
 
     DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
@@ -459,7 +468,7 @@
 void V4L2VideoDecodeAccelerator::CreateEGLImageFor(
     size_t buffer_index,
     int32_t picture_buffer_id,
-    std::vector<base::ScopedFD> dmabuf_fds,
+    gfx::NativePixmapHandle handle,
     GLuint texture_id,
     const gfx::Size& size,
     const Fourcc fourcc) {
@@ -484,7 +493,7 @@
 
   EGLImageKHR egl_image = egl_image_device_->CreateEGLImage(
       egl_display_, gl_context->GetHandle(), texture_id, size, buffer_index,
-      fourcc.ToV4L2PixFmt(), dmabuf_fds);
+      fourcc, std::move(handle));
   if (egl_image == EGL_NO_IMAGE_KHR) {
     VLOGF(1) << "could not create EGLImageKHR,"
              << " index=" << buffer_index << " texture_id=" << texture_id;
@@ -575,48 +584,22 @@
     return;
   }
 
-  std::vector<base::ScopedFD> dmabuf_fds;
-  for (auto& plane : handle.planes) {
-    dmabuf_fds.push_back(std::move(plane.fd));
-  }
-
-  // If the driver does not accept as many fds as we received from the client,
-  // we have to check if the additional fds are actually duplicated fds pointing
-  // to previous planes; if so, we can close the duplicates and keep only the
-  // original fd(s).
-  // Assume that an fd is a duplicate of a previous plane's fd if offset != 0.
-  // Otherwise, if offset == 0, return error as it may be pointing to a new
-  // plane.
-  for (size_t i = dmabuf_fds.size() - 1; i >= egl_image_planes_count_; i--) {
-    if (handle.planes[i].offset == 0) {
-      VLOGF(1) << "The dmabuf fd points to a new buffer, ";
-      NOTIFY_ERROR(INVALID_ARGUMENT);
-      return;
-    }
-    // Drop safely, because this fd is duplicate dmabuf fd pointing to previous
-    // buffer and the appropriate address can be accessed by associated offset.
-    dmabuf_fds.pop_back();
-  }
-
   for (const auto& plane : handle.planes) {
     DVLOGF(3) << ": offset=" << plane.offset << ", stride=" << plane.stride;
   }
 
-  ImportBufferForPictureTask(picture_buffer_id, std::move(dmabuf_fds),
-                             handle.planes[0].stride);
+  ImportBufferForPictureTask(picture_buffer_id, std::move(handle));
 }
 
 void V4L2VideoDecodeAccelerator::ImportBufferForPictureTask(
     int32_t picture_buffer_id,
-    std::vector<base::ScopedFD> dmabuf_fds,
-    int32_t stride) {
+    gfx::NativePixmapHandle handle) {
   DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id
-            << ", dmabuf_fds.size()=" << dmabuf_fds.size()
-            << ", stride=" << stride;
+            << ", handle.planes.size()=" << handle.planes.size();
   DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
   TRACE_EVENT2("media,gpu", "V4L2VDA::ImportBufferForPictureTask",
-               "picture_buffer_id", picture_buffer_id, "dmabuf_fds_size",
-               dmabuf_fds.size());
+               "picture_buffer_id", picture_buffer_id, "handle.planes",
+               handle.planes.size());
 
   if (IsDestroyPending())
     return;
@@ -636,27 +619,40 @@
     return;
   }
 
-  // TODO(crbug.com/982172): This must be done in AssignPictureBuffers().
-  // However the size of PictureBuffer might not be adjusted by ARC++. So we
-  // keep this until ARC++ side is fixed.
-  int plane_horiz_bits_per_pixel = VideoFrame::PlaneHorizontalBitsPerPixel(
-      egl_image_format_fourcc_->ToVideoPixelFormat(), 0);
-  if (plane_horiz_bits_per_pixel == 0 ||
-      (stride * 8) % plane_horiz_bits_per_pixel != 0) {
-    VLOGF(1) << "Invalid format " << egl_image_format_fourcc_->ToString()
-             << " or stride " << stride;
+  if (!output_wait_map_.count(iter->picture_id)) {
+    VLOGF(1) << "Passed buffer is not waiting to be imported";
     NOTIFY_ERROR(INVALID_ARGUMENT);
     return;
   }
 
-  int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel;
-  // If this is the first picture, then adjust the EGL width.
-  // Otherwise just check that it remains the same.
-  if (decoder_state_ == kAwaitingPictureBuffers) {
-    DCHECK_GE(adjusted_coded_width, egl_image_size_.width());
-    egl_image_size_.set_width(adjusted_coded_width);
+  // TODO(crbug.com/982172): This must be done in AssignPictureBuffers().
+  // However the size of PictureBuffer might not be adjusted by ARC++. So we
+  // keep this until ARC++ side is fixed.
+  if (output_mode_ == Config::OutputMode::IMPORT) {
+    DCHECK_GT(handle.planes.size(), 0u);
+    const int32_t stride = handle.planes[0].stride;
+    int plane_horiz_bits_per_pixel = VideoFrame::PlaneHorizontalBitsPerPixel(
+        egl_image_format_fourcc_->ToVideoPixelFormat(), 0);
+    if (plane_horiz_bits_per_pixel == 0 ||
+        (stride * 8) % plane_horiz_bits_per_pixel != 0) {
+      VLOGF(1) << "Invalid format " << egl_image_format_fourcc_->ToString()
+               << " or stride " << stride;
+      NOTIFY_ERROR(INVALID_ARGUMENT);
+      return;
+    }
+
+    int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel;
+    // If this is the first picture, then adjust the EGL width.
+    // Otherwise just check that it remains the same.
+    if (decoder_state_ == kAwaitingPictureBuffers) {
+      DCHECK_GE(adjusted_coded_width, egl_image_size_.width());
+      egl_image_size_.set_width(adjusted_coded_width);
+    }
+    DCHECK_EQ(egl_image_size_.width(), adjusted_coded_width);
+
+    DVLOGF(3) << "Original egl_image_size=" << egl_image_size_.ToString()
+              << ", adjusted coded width=" << adjusted_coded_width;
   }
-  DCHECK_EQ(egl_image_size_.width(), adjusted_coded_width);
 
   if (image_processor_device_ && !image_processor_) {
     DCHECK_EQ(kAwaitingPictureBuffers, decoder_state_);
@@ -664,8 +660,6 @@
     // the decoder state. The client may adjust the coded width. We don't have
     // the final coded size in AssignPictureBuffers yet. Use the adjusted coded
     // width to create the image processor.
-    DVLOGF(3) << "Original egl_image_size=" << egl_image_size_.ToString()
-              << ", adjusted coded width=" << adjusted_coded_width;
     if (!CreateImageProcessor())
       return;
   }
@@ -679,8 +673,10 @@
     DVLOGF(3) << "Change state to kDecoding";
   }
 
+  // If we are importing, create the output VideoFrame that we will render
+  // into.
   if (output_mode_ == Config::OutputMode::IMPORT) {
-    DCHECK_EQ(egl_image_planes_count_, dmabuf_fds.size());
+    DCHECK_GT(handle.planes.size(), 0u);
     DCHECK(!iter->output_frame);
 
     auto layout = VideoFrameLayout::Create(
@@ -690,9 +686,21 @@
       NOTIFY_ERROR(INVALID_ARGUMENT);
       return;
     }
+
+    // Duplicate the buffer FDs for the VideoFrame instance.
+    std::vector<base::ScopedFD> duped_fds;
+    for (const gfx::NativePixmapPlane& plane : handle.planes) {
+      duped_fds.emplace_back(HANDLE_EINTR(dup(plane.fd.get())));
+      if (!duped_fds.back().is_valid()) {
+        VPLOG(1) << "Failed to duplicate plane FD!";
+        NOTIFY_ERROR(PLATFORM_FAILURE);
+        return;
+      }
+    }
+
     iter->output_frame = VideoFrame::WrapExternalDmabufs(
         *layout, gfx::Rect(visible_size_), visible_size_,
-        DuplicateFDs(dmabuf_fds), base::TimeDelta());
+        DuplicateFDs(duped_fds), base::TimeDelta());
   }
 
   if (iter->texture_id != 0) {
@@ -703,18 +711,20 @@
                          device_, egl_display_, iter->egl_image));
     }
 
-    size_t index = iter - output_buffer_map_.begin();
     // If we are not using an image processor, create the EGL image ahead of
     // time since we already have its DMABUF fds. It is guaranteed that
     // CreateEGLImageFor will run before the picture is passed to the client
     // because the picture will need to be cleared on the child thread first.
     if (!image_processor_) {
+      DCHECK_GT(handle.planes.size(), 0u);
+      size_t index = iter - output_buffer_map_.begin();
+
       child_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&V4L2VideoDecodeAccelerator::CreateEGLImageFor,
                          weak_this_, index, picture_buffer_id,
-                         std::move(dmabuf_fds), iter->texture_id,
-                         egl_image_size_, *egl_image_format_fourcc_));
+                         std::move(handle), iter->texture_id, egl_image_size_,
+                         *egl_image_format_fourcc_));
 
       // Early return, AssignEGLImage will make the buffer available for
       // decoding once the EGL image is created.
@@ -1595,12 +1605,10 @@
     case V4L2_MEMORY_MMAP:
       ret = std::move(buffer).QueueMMap();
       break;
-    case V4L2_MEMORY_DMABUF: {
-      const auto& fds = output_record.output_frame->DmabufFds();
-      DCHECK_EQ(output_planes_count_, fds.size());
-      ret = std::move(buffer).QueueDMABuf(fds);
+    case V4L2_MEMORY_DMABUF:
+      ret = std::move(buffer).QueueDMABuf(
+          output_record.output_frame->DmabufFds());
       break;
-    }
     default:
       NOTREACHED();
   }
@@ -2187,28 +2195,29 @@
     const struct v4l2_format& format,
     const gfx::Size& visible_size) {
   DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
-  output_planes_count_ = format.fmt.pix_mp.num_planes;
+  size_t egl_image_planes_count;
+
   coded_size_.SetSize(format.fmt.pix_mp.width, format.fmt.pix_mp.height);
   visible_size_ = visible_size;
   if (image_processor_device_) {
     egl_image_size_ = visible_size_;
-    egl_image_planes_count_ = 0;
+    egl_image_planes_count = 0;
     if (!V4L2ImageProcessorBackend::TryOutputFormat(
             output_format_fourcc_->ToV4L2PixFmt(),
             egl_image_format_fourcc_->ToV4L2PixFmt(), coded_size_,
-            &egl_image_size_, &egl_image_planes_count_)) {
+            &egl_image_size_, &egl_image_planes_count)) {
       VLOGF(1) << "Fail to get output size and plane count of processor";
       return false;
     }
   } else {
     egl_image_size_ = coded_size_;
-    egl_image_planes_count_ = output_planes_count_;
+    egl_image_planes_count = format.fmt.pix_mp.num_planes;
   }
   VLOGF(2) << "new resolution: " << coded_size_.ToString()
            << ", visible size: " << visible_size_.ToString()
-           << ", decoder output planes count: " << output_planes_count_
+           << ", decoder output planes count: " << format.fmt.pix_mp.num_planes
            << ", EGLImage size: " << egl_image_size_.ToString()
-           << ", EGLImage plane count: " << egl_image_planes_count_;
+           << ", EGLImage plane count: " << egl_image_planes_count;
 
   return CreateOutputBuffers();
 }
@@ -2325,8 +2334,9 @@
   memset(&fmtdesc, 0, sizeof(fmtdesc));
   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
-    if (device_->CanCreateEGLImageFrom(fmtdesc.pixelformat)) {
-      output_format_fourcc_ = Fourcc::FromV4L2PixFmt(fmtdesc.pixelformat);
+    auto fourcc = Fourcc::FromV4L2PixFmt(fmtdesc.pixelformat);
+    if (fourcc && device_->CanCreateEGLImageFrom(*fourcc)) {
+      output_format_fourcc_ = *fourcc;
       break;
     }
     ++fmtdesc.index;
@@ -2673,13 +2683,15 @@
   // uncleared status.
   if (ip_output_record.texture_id != 0 && !ip_output_record.cleared) {
     DCHECK(frame->HasDmaBufs());
+
     child_task_runner_->PostTask(
         FROM_HERE,
-        base::BindOnce(&V4L2VideoDecodeAccelerator::CreateEGLImageFor,
-                       weak_this_, ip_buffer_index, ip_output_record.picture_id,
-                       media::DuplicateFDs(frame->DmabufFds()),
-                       ip_output_record.texture_id, egl_image_size_,
-                       *egl_image_format_fourcc_));
+        base::BindOnce(
+            &V4L2VideoDecodeAccelerator::CreateEGLImageFor, weak_this_,
+            ip_buffer_index, ip_output_record.picture_id,
+            CreateGpuMemoryBufferHandle(frame.get()).native_pixmap_handle,
+            ip_output_record.texture_id, egl_image_size_,
+            *egl_image_format_fourcc_));
   }
 
   // Remove our job from the IP jobs queue
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.h b/media/gpu/v4l2/v4l2_video_decode_accelerator.h
index 33648c51..3901f8d 100644
--- a/media/gpu/v4l2/v4l2_video_decode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.h
@@ -239,28 +239,24 @@
   // via AssignPictureBuffers() on decoder thread.
   void AssignPictureBuffersTask(const std::vector<PictureBuffer>& buffers);
 
-  // Use buffer backed by dmabuf file descriptors in |dmabuf_fds| for the
-  // OutputRecord associated with |picture_buffer_id|, taking ownership of the
-  // file descriptors. |stride| is the number of bytes from one row of pixels
-  // to the next row.
+  // Use buffer backed by |handle| for the OutputRecord associated with
+  // |picture_buffer_id|. |handle| does not need to be valid if we are in
+  // ALLOCATE mode and using an image processor.
   void ImportBufferForPictureTask(int32_t picture_buffer_id,
-                                  std::vector<base::ScopedFD> dmabuf_fds,
-                                  int32_t stride);
+                                  gfx::NativePixmapHandle handle);
 
-  // Check |planes| and |dmabuf_fds| are valid in import mode, besides
-  // ImportBufferForPicture.
+  // Check |handle| is valid in import mode, besides ImportBufferForPicture.
   void ImportBufferForPictureForImportTask(int32_t picture_buffer_id,
                                            VideoPixelFormat pixel_format,
                                            gfx::NativePixmapHandle handle);
 
   // Create an EGLImage for the buffer associated with V4L2 |buffer_index| and
-  // for |picture_buffer_id|, backed by dmabuf file descriptors in
-  // |passed_dmabuf_fds|, taking ownership of them.
+  // for |picture_buffer_id|, and backed by |handle|.
   // The buffer should be bound to |texture_id| and is of |size| and format
   // described by |fourcc|.
   void CreateEGLImageFor(size_t buffer_index,
                          int32_t picture_buffer_id,
-                         std::vector<base::ScopedFD> dmabuf_fds,
+                         gfx::NativePixmapHandle handle,
                          GLuint texture_id,
                          const gfx::Size& size,
                          const Fourcc fourcc);
@@ -517,10 +513,9 @@
   //
   // Hardware state and associated queues.  Since decoder_thread_ services
   // the hardware, decoder_thread_ owns these too.
-  // output_buffer_map_ and output_planes_count_ are an
-  // exception during the buffer (re)allocation sequence, when the
-  // decoder_thread_ is blocked briefly while the Child thread manipulates
-  // them.
+  // output_buffer_map_ is an exception during the buffer (re)allocation
+  // sequence, when the decoder_thread_ is blocked briefly while the Child
+  // thread manipulates them.
   //
 
   base::Optional<V4L2WritableBufferRef> current_input_buffer_;
@@ -551,9 +546,6 @@
   // Required size of DPB for decoding.
   int output_dpb_size_;
 
-  // Number of planes (i.e. separate memory buffers) for output.
-  size_t output_planes_count_;
-
   // Pictures that are ready but not sent to PictureReady yet.
   base::queue<PictureRecord> pending_picture_ready_;
 
@@ -603,8 +595,6 @@
   base::Optional<Fourcc> egl_image_format_fourcc_;
   // The logical dimensions of EGLImage buffer in pixels.
   gfx::Size egl_image_size_;
-  // Number of planes for EGLImage.
-  size_t egl_image_planes_count_;
 
   // Input format V4L2 fourccs this class supports.
   static const uint32_t supported_input_fourccs_[];
diff --git a/media/gpu/vaapi/vaapi_image_processor_backend.cc b/media/gpu/vaapi/vaapi_image_processor_backend.cc
index 4fd38d4..dd9bbe8b 100644
--- a/media/gpu/vaapi/vaapi_image_processor_backend.cc
+++ b/media/gpu/vaapi/vaapi_image_processor_backend.cc
@@ -181,9 +181,9 @@
     return;
   }
   // VA-API performs pixel format conversion and scaling without any filters.
-  if (vaapi_wrapper_->BlitSurface(*src_va_surface, *dst_va_surface,
-                                  input_frame->visible_rect(),
-                                  output_frame->visible_rect())) {
+  if (!vaapi_wrapper_->BlitSurface(*src_va_surface, *dst_va_surface,
+                                   input_frame->visible_rect(),
+                                   output_frame->visible_rect())) {
     // Failed to execute BlitSurface(). Since VaapiWrapper has invoked
     // ReportToUMA(), calling error_cb_ here is not needed.
     return;
diff --git a/media/renderers/audio_renderer_impl.cc b/media/renderers/audio_renderer_impl.cc
index f899b6e..5020dd4 100644
--- a/media/renderers/audio_renderer_impl.cc
+++ b/media/renderers/audio_renderer_impl.cc
@@ -338,7 +338,7 @@
 void AudioRendererImpl::Initialize(DemuxerStream* stream,
                                    CdmContext* cdm_context,
                                    RendererClient* client,
-                                   const PipelineStatusCB& init_cb) {
+                                   PipelineStatusCallback init_cb) {
   DVLOG(1) << __func__;
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(client);
@@ -360,7 +360,7 @@
 
   // Always post |init_cb_| because |this| could be destroyed if initialization
   // failed.
-  init_cb_ = BindToCurrentLoop(init_cb);
+  init_cb_ = BindToCurrentLoop(std::move(init_cb));
 
   // Retrieve hardware device parameters asynchronously so we don't block the
   // media thread on synchronous IPC.
diff --git a/media/renderers/audio_renderer_impl.h b/media/renderers/audio_renderer_impl.h
index 443bff4..480373b 100644
--- a/media/renderers/audio_renderer_impl.h
+++ b/media/renderers/audio_renderer_impl.h
@@ -84,7 +84,7 @@
   void Initialize(DemuxerStream* stream,
                   CdmContext* cdm_context,
                   RendererClient* client,
-                  const PipelineStatusCB& init_cb) override;
+                  PipelineStatusCallback init_cb) override;
   TimeSource* GetTimeSource() override;
   void Flush(base::OnceClosure callback) override;
   void StartPlaying() override;
@@ -249,7 +249,7 @@
   RendererClient* client_;
 
   // Callback provided during Initialize().
-  PipelineStatusCB init_cb_;
+  PipelineStatusCallback init_cb_;
 
   // Callback provided to Flush().
   base::OnceClosure flush_cb_;
diff --git a/media/renderers/renderer_impl_unittest.cc b/media/renderers/renderer_impl_unittest.cc
index 0a44e633..7911b741 100644
--- a/media/renderers/renderer_impl_unittest.cc
+++ b/media/renderers/renderer_impl_unittest.cc
@@ -23,6 +23,7 @@
 
 using ::base::test::RunCallback;
 using ::base::test::RunClosure;
+using ::base::test::RunOnceCallback;
 using ::base::test::RunOnceClosure;
 using ::testing::_;
 using ::testing::DoAll;
@@ -123,16 +124,16 @@
 
   // Sets up expectations to allow the audio renderer to initialize.
   void SetAudioRendererInitializeExpectations(PipelineStatus status) {
-    EXPECT_CALL(*audio_renderer_, Initialize(audio_stream_.get(), _, _, _))
-        .WillOnce(
-            DoAll(SaveArg<2>(&audio_renderer_client_), RunCallback<3>(status)));
+    EXPECT_CALL(*audio_renderer_, OnInitialize(audio_stream_.get(), _, _, _))
+        .WillOnce(DoAll(SaveArg<2>(&audio_renderer_client_),
+                        RunOnceCallback<3>(status)));
   }
 
   // Sets up expectations to allow the video renderer to initialize.
   void SetVideoRendererInitializeExpectations(PipelineStatus status) {
-    EXPECT_CALL(*video_renderer_, Initialize(video_stream_.get(), _, _, _, _))
-        .WillOnce(
-            DoAll(SaveArg<2>(&video_renderer_client_), RunCallback<4>(status)));
+    EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _))
+        .WillOnce(DoAll(SaveArg<2>(&video_renderer_client_),
+                        RunOnceCallback<4>(status)));
   }
 
   void InitializeAndExpect(PipelineStatus start_status) {
@@ -397,7 +398,7 @@
 
   SetAudioRendererInitializeExpectations(PIPELINE_OK);
   // Not returning the video initialization callback.
-  EXPECT_CALL(*video_renderer_, Initialize(video_stream_.get(), _, _, _, _));
+  EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
 
   InitializeAndExpect(PIPELINE_ERROR_ABORT);
   EXPECT_EQ(PIPELINE_OK, initialization_status_);
@@ -431,7 +432,7 @@
   SetAudioRendererInitializeExpectations(PIPELINE_OK);
   // Not returning the video initialization callback. So initialization will
   // be pending.
-  EXPECT_CALL(*video_renderer_, Initialize(video_stream_.get(), _, _, _, _));
+  EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
 
   // SetCdm() will trigger the initialization to start. But it will not complete
   // because the |video_renderer_| is not returning the initialization callback.
@@ -697,10 +698,10 @@
   SetAudioRendererInitializeExpectations(PIPELINE_OK);
 
   // Force an audio error to occur during video renderer initialization.
-  EXPECT_CALL(*video_renderer_, Initialize(video_stream_.get(), _, _, _, _))
+  EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _))
       .WillOnce(DoAll(SetError(&audio_renderer_client_, PIPELINE_ERROR_DECODE),
                       SaveArg<2>(&video_renderer_client_),
-                      RunCallback<4>(PIPELINE_OK)));
+                      RunOnceCallback<4>(PIPELINE_OK)));
 
   InitializeAndExpect(PIPELINE_ERROR_DECODE);
 }
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc
index 8258bb13..1bb2c1d 100644
--- a/media/renderers/video_renderer_impl.cc
+++ b/media/renderers/video_renderer_impl.cc
@@ -211,7 +211,7 @@
     CdmContext* cdm_context,
     RendererClient* client,
     const TimeSource::WallClockTimeCB& wall_clock_time_cb,
-    const PipelineStatusCB& init_cb) {
+    PipelineStatusCallback init_cb) {
   DCHECK(task_runner_->BelongsToCurrentThread());
   TRACE_EVENT_ASYNC_BEGIN0("media", "VideoRendererImpl::Initialize", this);
 
@@ -246,7 +246,7 @@
 
   // Always post |init_cb_| because |this| could be destroyed if initialization
   // failed.
-  init_cb_ = BindToCurrentLoop(init_cb);
+  init_cb_ = BindToCurrentLoop(std::move(init_cb));
 
   client_ = client;
   wall_clock_time_cb_ = wall_clock_time_cb;
diff --git a/media/renderers/video_renderer_impl.h b/media/renderers/video_renderer_impl.h
index 3c35a3e..fe9a6fa 100644
--- a/media/renderers/video_renderer_impl.h
+++ b/media/renderers/video_renderer_impl.h
@@ -66,7 +66,7 @@
                   CdmContext* cdm_context,
                   RendererClient* client,
                   const TimeSource::WallClockTimeCB& wall_clock_time_cb,
-                  const PipelineStatusCB& init_cb) override;
+                  PipelineStatusCallback init_cb) override;
   void Flush(base::OnceClosure callback) override;
   void StartPlayingFrom(base::TimeDelta timestamp) override;
   void OnTimeProgressing() override;
@@ -266,7 +266,7 @@
   BufferingState buffering_state_;
 
   // Playback operation callbacks.
-  PipelineStatusCB init_cb_;
+  PipelineStatusCallback init_cb_;
   base::OnceClosure flush_cb_;
   TimeSource::WallClockTimeCB wall_clock_time_cb_;
 
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc
index 80846a342..bd2c98a 100644
--- a/media/renderers/video_renderer_impl_unittest.cc
+++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -133,7 +133,7 @@
   }
 
   void CallInitialize(MockDemuxerStream* demuxer_stream,
-                      const PipelineStatusCB& status_cb,
+                      PipelineStatusCallback status_cb,
                       bool low_delay,
                       bool expect_success) {
     if (low_delay)
@@ -145,7 +145,7 @@
         demuxer_stream, nullptr, &mock_cb_,
         base::BindRepeating(&WallClockTimeSource::GetWallClockTimes,
                             base::Unretained(&time_source_)),
-        status_cb);
+        std::move(status_cb));
   }
 
   void StartPlayingFrom(int milliseconds) {
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index 5f9de46..b3db99c 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -427,13 +427,6 @@
   std::move(callback).Run(ValidateResponse(result));
 }
 
-void WebSocketBasicHandshakeStream::OnFinishOpeningHandshake() {
-  DCHECK(http_response_info_);
-  WebSocketDispatchOnFinishOpeningHandshake(
-      connect_delegate_, url_, http_response_info_->headers,
-      http_response_info_->remote_endpoint, http_response_info_->response_time);
-}
-
 int WebSocketBasicHandshakeStream::ValidateResponse(int rv) {
   DCHECK(http_response_info_);
   // Most net errors happen during connection, so they are not seen by this
@@ -445,7 +438,6 @@
     base::UmaHistogramSparse("Net.WebSocket.ResponseCode", response_code);
     switch (response_code) {
       case HTTP_SWITCHING_PROTOCOLS:
-        OnFinishOpeningHandshake();
         return ValidateUpgradeResponse(headers);
 
       // We need to pass these through for authentication to work.
@@ -467,7 +459,6 @@
               "Error during WebSocket handshake: Unexpected response code: %d",
               headers->response_code()));
         }
-        OnFinishOpeningHandshake();
         result_ = HandshakeResult::INVALID_STATUS;
         return ERR_INVALID_RESPONSE;
     }
@@ -479,7 +470,6 @@
     }
     OnFailure(std::string("Error during WebSocket handshake: ") +
               ErrorToString(rv));
-    OnFinishOpeningHandshake();
     // Some error codes (for example ERR_CONNECTION_CLOSED) get changed to OK at
     // higher levels. To prevent an unvalidated connection getting erroneously
     // upgraded, don't pass through the status code unchanged if it is
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h
index 31986aa..3e2fd62 100644
--- a/net/websockets/websocket_basic_handshake_stream.h
+++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -94,8 +94,6 @@
   // the connection has been accepted.
   void ReadResponseHeadersCallback(CompletionOnceCallback callback, int result);
 
-  void OnFinishOpeningHandshake();
-
   // Validates the response and sends the finished handshake event.
   int ValidateResponse(int rv);
 
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index 6577a6a3c..95cd490 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -181,8 +181,10 @@
     creator_->OnCreateURLRequest(request);
   }
 
-  void OnSuccess(std::unique_ptr<WebSocketStream> stream) override {
-    creator_->OnConnectSuccess(std::move(stream));
+  void OnSuccess(
+      std::unique_ptr<WebSocketStream> stream,
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
+    creator_->OnConnectSuccess(std::move(stream), std::move(response));
     // |this| may have been deleted.
   }
 
@@ -196,11 +198,6 @@
     creator_->OnStartOpeningHandshake(std::move(request));
   }
 
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
-    creator_->OnFinishOpeningHandshake(std::move(response));
-  }
-
   void OnSSLCertificateError(
       std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
           ssl_error_callbacks,
@@ -457,7 +454,8 @@
 }
 
 void WebSocketChannel::OnConnectSuccess(
-    std::unique_ptr<WebSocketStream> stream) {
+    std::unique_ptr<WebSocketStream> stream,
+    std::unique_ptr<WebSocketHandshakeResponseInfo> response) {
   DCHECK(stream);
   DCHECK_EQ(CONNECTING, state_);
 
@@ -471,9 +469,9 @@
   // TODO(ricea): Get flow control information from the WebSocketStream once we
   // have a multiplexing WebSocketStream.
   current_send_quota_ = send_quota_high_water_mark_;
-  event_interface_->OnAddChannelResponse(stream_->GetSubProtocol(),
-                                         stream_->GetExtensions(),
-                                         send_quota_high_water_mark_);
+  event_interface_->OnAddChannelResponse(
+      std::move(response), stream_->GetSubProtocol(), stream_->GetExtensions(),
+      send_quota_high_water_mark_);
   // |this| may have been deleted after OnAddChannelResponse.
 }
 
@@ -516,11 +514,6 @@
   event_interface_->OnStartOpeningHandshake(std::move(request));
 }
 
-void WebSocketChannel::OnFinishOpeningHandshake(
-    std::unique_ptr<WebSocketHandshakeResponseInfo> response) {
-  event_interface_->OnFinishOpeningHandshake(std::move(response));
-}
-
 ChannelState WebSocketChannel::WriteFrames() {
   int result = OK;
   do {
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h
index 7fc729ef..30260639 100644
--- a/net/websockets/websocket_channel.h
+++ b/net/websockets/websocket_channel.h
@@ -149,11 +149,6 @@
   void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request);
 
-  // Called when the stream ends the WebSocket Opening Handshake.
-  // This method is public for testing.
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response);
-
   // The renderer calls AddReceiveFlowControlQuota() to the browser per
   // recerving this amount of data so that the browser can continue sending
   // remaining data to the renderer.
@@ -206,7 +201,9 @@
 
   // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
   // success to the event interface. May delete |this|.
-  void OnConnectSuccess(std::unique_ptr<WebSocketStream> stream);
+  void OnConnectSuccess(
+      std::unique_ptr<WebSocketStream> stream,
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response);
 
   // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
   // failure to the event interface. May delete |this|.
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index a9647a60..311918d7 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -167,8 +167,9 @@
   }
 
   MOCK_METHOD1(OnCreateURLRequest, void(URLRequest*));
-  MOCK_METHOD3(OnAddChannelResponse,
-               void(const std::string&,
+  MOCK_METHOD4(OnAddChannelResponse,
+               void(std::unique_ptr<WebSocketHandshakeResponseInfo> response,
+                    const std::string&,
                     const std::string&,
                     int64_t));  // NOLINT
   MOCK_METHOD3(OnDataFrameVector,
@@ -187,10 +188,6 @@
       std::unique_ptr<WebSocketHandshakeRequestInfo>) override {
     OnStartOpeningHandshakeCalled();
   }
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo>) override {
-    OnFinishOpeningHandshakeCalled();
-  }
   void OnSSLCertificateError(
       std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
       const GURL& url,
@@ -211,7 +208,6 @@
   }
 
   MOCK_METHOD0(OnStartOpeningHandshakeCalled, void());  // NOLINT
-  MOCK_METHOD0(OnFinishOpeningHandshakeCalled, void());  // NOLINT
   MOCK_METHOD4(
       OnSSLCertificateErrorCalled,
       void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool));  // NOLINT
@@ -226,9 +222,11 @@
 // implementation but are not verifying how it is used.
 class FakeWebSocketEventInterface : public WebSocketEventInterface {
   void OnCreateURLRequest(URLRequest* request) override {}
-  void OnAddChannelResponse(const std::string& selected_protocol,
-                            const std::string& extensions,
-                            int64_t send_flow_control_quota) override {}
+  void OnAddChannelResponse(
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response,
+      const std::string& selected_protocol,
+      const std::string& extensions,
+      int64_t send_flow_control_quota) override {}
   void OnDataFrame(bool fin,
                    WebSocketMessageType type,
                    base::span<const char> data_span) override {}
@@ -241,8 +239,6 @@
                      const std::string& reason) override {}
   void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {}
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
   void OnSSLCertificateError(
       std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
       const GURL& url,
@@ -823,7 +819,8 @@
   virtual void CreateChannelAndConnectSuccessfully() {
     CreateChannelAndConnect();
     connect_data_.argument_saver.connect_delegate->OnSuccess(
-        std::move(stream_));
+        std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
+                                GURL(), nullptr, IPEndPoint(), base::Time()));
     ignore_result(channel_->ReadFrames());
   }
 
@@ -933,7 +930,7 @@
     // whether these methods are called or not.
     EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
     EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _))
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _))
         .Times(AnyNumber());
     EXPECT_CALL(*event_interface_, OnDataFrameVector(_, _, _))
         .Times(AnyNumber());
@@ -964,7 +961,7 @@
     set_stream(std::make_unique<WriteableFakeWebSocketStream>());
     // For the purpose of the tests using this fixture, it doesn't matter
     // whether these methods are called or not.
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _))
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _))
         .Times(AnyNumber());
   }
 };
@@ -1009,11 +1006,13 @@
 
 TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
   // false means success.
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse("", "", _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "", "", _));
 
   CreateChannelAndConnect();
 
-  connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
+  connect_data_.argument_saver.connect_delegate->OnSuccess(
+      std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
+                              GURL(), nullptr, IPEndPoint(), base::Time()));
   ignore_result(channel_->ReadFrames());
 }
 
@@ -1032,23 +1031,27 @@
 }
 
 TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse("Bob", "", _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "Bob", "", _));
 
   CreateChannelAndConnect();
 
   connect_data_.argument_saver.connect_delegate->OnSuccess(
-      std::make_unique<FakeWebSocketStream>("Bob", ""));
+      std::make_unique<FakeWebSocketStream>("Bob", ""),
+      std::make_unique<WebSocketHandshakeResponseInfo>(
+          GURL(), nullptr, IPEndPoint(), base::Time()));
   ignore_result(channel_->ReadFrames());
 }
 
 TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) {
   EXPECT_CALL(*event_interface_,
-              OnAddChannelResponse("", "extension1, extension2", _));
+              OnAddChannelResponse(_, "", "extension1, extension2", _));
 
   CreateChannelAndConnect();
 
   connect_data_.argument_saver.connect_delegate->OnSuccess(
-      std::make_unique<FakeWebSocketStream>("", "extension1, extension2"));
+      std::make_unique<FakeWebSocketStream>("", "extension1, extension2"),
+      std::make_unique<WebSocketHandshakeResponseInfo>(
+          GURL(), nullptr, IPEndPoint(), base::Time()));
   ignore_result(channel_->ReadFrames());
 }
 
@@ -1063,7 +1066,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("HELLO")));
@@ -1085,7 +1088,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_, OnClosingHandshake());
     EXPECT_CALL(
         *event_interface_,
@@ -1109,7 +1112,7 @@
   Checkpoint checkpoint;
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_, HasPendingDataFrames())
         .WillOnce(Return(false))
         .WillOnce(Return(true))
@@ -1139,7 +1142,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
   }
@@ -1158,7 +1161,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
@@ -1185,7 +1188,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("HELLO")));
@@ -1223,7 +1226,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("THREE")));
@@ -1256,7 +1259,7 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(
       *event_interface_,
       OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
@@ -1271,7 +1274,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
   }
@@ -1288,7 +1291,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
   }
@@ -1307,7 +1310,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(
         *event_interface_,
         OnFailChannel(
@@ -1328,7 +1331,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnFailChannel("Unrecognized frame opcode: 4"));
   }
@@ -1357,7 +1360,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("SPLIT ")));
@@ -1379,7 +1382,7 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
 
   CreateChannelAndConnectSuccessfully();
   base::RunLoop().RunUntilIdle();
@@ -1397,7 +1400,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(
         *event_interface_,
         OnFailChannel(
@@ -1414,7 +1417,7 @@
   set_stream(std::make_unique<WriteableFakeWebSocketStream>());
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   }
 
   CreateChannelAndConnectSuccessfully();
@@ -1431,7 +1434,7 @@
   Checkpoint checkpoint;
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
     EXPECT_CALL(checkpoint, Call(2));
@@ -1451,7 +1454,7 @@
   Checkpoint checkpoint;
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
     EXPECT_CALL(checkpoint, Call(2));
@@ -1481,7 +1484,7 @@
   {
     InSequence s;
     EXPECT_CALL(*event_interface_,
-                OnAddChannelResponse(_, _, kDefaultInitialQuota));
+                OnAddChannelResponse(_, _, _, kDefaultInitialQuota));
     EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded"));
   }
 
@@ -1497,7 +1500,7 @@
   Checkpoint checkpoint;
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(*event_interface_,
                 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
@@ -1517,7 +1520,7 @@
   set_stream(std::make_unique<EchoeyFakeWebSocketStream>());
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDropChannel(true, kWebSocketNormalClosure, "Fred"));
   }
@@ -1544,7 +1547,7 @@
 // connection reset.
 TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
   set_stream(std::make_unique<ResetOnWriteFakeWebSocketStream>());
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
 
   EXPECT_CALL(*event_interface_,
               OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""))
@@ -1567,7 +1570,7 @@
   stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
                                  ERR_CONNECTION_CLOSED);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(*event_interface_, OnClosingHandshake());
   EXPECT_CALL(*event_interface_,
               OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
@@ -1585,7 +1588,7 @@
   stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
                                  ERR_CONNECTION_CLOSED);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(*event_interface_, OnClosingHandshake());
   EXPECT_CALL(*event_interface_,
               OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
@@ -1600,7 +1603,7 @@
   stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
                                  ERR_WS_PROTOCOL_ERROR);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
 
   EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
 
@@ -1613,7 +1616,7 @@
   stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
                                  ERR_WS_PROTOCOL_ERROR);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
 
   CreateChannelAndConnectSuccessfully();
@@ -1623,7 +1626,7 @@
 TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) {
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
   }
 
@@ -1637,30 +1640,10 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(WebSocketChannelEventInterfaceTest, FinishHandshakeRequest) {
-  {
-    InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
-    EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
-  }
-
-  CreateChannelAndConnectSuccessfully();
-
-  auto response_headers =
-      base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
-  auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>(
-      GURL("ws://www.example.com/"), response_headers, IPEndPoint(),
-      base::Time());
-  connect_data_.argument_saver.connect_delegate->OnFinishOpeningHandshake(
-      std::move(response_info));
-  base::RunLoop().RunUntilIdle();
-}
-
 TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) {
   {
     InSequence s;
     EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
-    EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
     EXPECT_CALL(*event_interface_, OnFailChannel("bye"));
   }
 
@@ -1676,7 +1659,6 @@
   auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>(
       url, response_headers, IPEndPoint(), base::Time());
   connect_delegate->OnStartOpeningHandshake(std::move(request_info));
-  connect_delegate->OnFinishOpeningHandshake(std::move(response_info));
 
   connect_delegate->OnFailure("bye");
   base::RunLoop().RunUntilIdle();
@@ -1692,7 +1674,7 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
 
   {
     InSequence s;
@@ -1712,7 +1694,7 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(
       *event_interface_,
       OnFailChannel(
@@ -1730,7 +1712,7 @@
        NOT_MASKED,  CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(
       *event_interface_,
       OnFailChannel(
@@ -1748,7 +1730,7 @@
        NOT_MASKED,  CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(
       *event_interface_,
       OnFailChannel(
@@ -1772,7 +1754,7 @@
   stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
                                std::move(raw_frames));
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(*event_interface_,
               OnFailChannel(
                   "One or more reserved bits are on: reserved1 = 1, "
@@ -1789,7 +1771,7 @@
   stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
                                  ERR_IO_PENDING);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   // This checkpoint object verifies that the OnDropChannel message comes after
   // the timeout.
   Checkpoint checkpoint;
@@ -1825,7 +1807,7 @@
        NOT_MASKED,  CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
   stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   Checkpoint checkpoint;
   TestClosure completion;
   {
@@ -1884,7 +1866,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("FOUR")));
@@ -1906,7 +1888,7 @@
   set_stream(std::move(stream));
   {
     InSequence s;
-    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
     EXPECT_CALL(*event_interface_,
                 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
                                   AsVector("FIRST MESSAGE")));
@@ -1940,7 +1922,7 @@
   set_stream(std::move(stream));
   Checkpoint checkpoint;
   InSequence s;
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(*event_interface_, HasPendingDataFrames()).WillOnce(Return(true));
   EXPECT_CALL(checkpoint, Call(1));
   EXPECT_CALL(*event_interface_, HasPendingDataFrames())
@@ -2340,7 +2322,7 @@
   stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
                                std::move(frames));
   set_stream(std::move(stream));
-  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
+  EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _));
   EXPECT_CALL(
       *event_interface_,
       OnDataFrameVector(
@@ -2456,7 +2438,7 @@
   set_stream(std::move(stream));
 
   EXPECT_CALL(*event_interface_,
-              OnAddChannelResponse(_, _, kDefaultInitialQuota));
+              OnAddChannelResponse(_, _, _, kDefaultInitialQuota));
   EXPECT_CALL(*event_interface_,
               OnFailChannel("Could not decode a text frame as UTF-8."));
 
@@ -2645,7 +2627,7 @@
   set_stream(std::move(stream));
 
   EXPECT_CALL(*event_interface_,
-              OnAddChannelResponse(_, _, kDefaultInitialQuota));
+              OnAddChannelResponse(_, _, _, kDefaultInitialQuota));
   EXPECT_CALL(*event_interface_,
               OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeBinary,
                                 AsVector("frame1")));
@@ -2667,7 +2649,7 @@
   set_stream(std::move(stream));
 
   EXPECT_CALL(*event_interface_,
-              OnAddChannelResponse(_, _, kDefaultInitialQuota));
+              OnAddChannelResponse(_, _, _, kDefaultInitialQuota));
   EXPECT_CALL(*event_interface_,
               OnFailChannel("Received unexpected continuation frame."));
 
@@ -2687,7 +2669,7 @@
   set_stream(std::move(stream));
 
   EXPECT_CALL(*event_interface_,
-              OnAddChannelResponse(_, _, kDefaultInitialQuota));
+              OnAddChannelResponse(_, _, _, kDefaultInitialQuota));
   EXPECT_CALL(
       *event_interface_,
       OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
@@ -2789,7 +2771,8 @@
     channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
         TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
     connect_data_.argument_saver.connect_delegate->OnSuccess(
-        std::move(stream_));
+        std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
+                                GURL(), nullptr, IPEndPoint(), base::Time()));
     ignore_result(channel_->ReadFrames());
   }
 };
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 87beb9f..4155c28 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -96,9 +96,11 @@
   // Implementation of WebSocketEventInterface.
   void OnCreateURLRequest(URLRequest* request) override {}
 
-  void OnAddChannelResponse(const std::string& selected_subprotocol,
-                            const std::string& extensions,
-                            int64_t send_flow_control_quota) override;
+  void OnAddChannelResponse(
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response,
+      const std::string& selected_subprotocol,
+      const std::string& extensions,
+      int64_t send_flow_control_quota) override;
 
   void OnDataFrame(bool fin,
                    WebSocketMessageType type,
@@ -119,9 +121,6 @@
   void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request) override;
 
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override;
-
   void OnSSLCertificateError(
       std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
       const GURL& url,
@@ -168,6 +167,7 @@
 }
 
 void ConnectTestingEventInterface::OnAddChannelResponse(
+    std::unique_ptr<WebSocketHandshakeResponseInfo> response,
     const std::string& selected_subprotocol,
     const std::string& extensions,
     int64_t send_flow_control_quota) {
@@ -198,9 +198,6 @@
 void ConnectTestingEventInterface::OnStartOpeningHandshake(
     std::unique_ptr<WebSocketHandshakeRequestInfo> request) {}
 
-void ConnectTestingEventInterface::OnFinishOpeningHandshake(
-    std::unique_ptr<WebSocketHandshakeResponseInfo> response) {}
-
 void ConnectTestingEventInterface::OnSSLCertificateError(
     std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
     const GURL& url,
diff --git a/net/websockets/websocket_event_interface.h b/net/websockets/websocket_event_interface.h
index 107b0a1..63eb1b4 100644
--- a/net/websockets/websocket_event_interface.h
+++ b/net/websockets/websocket_event_interface.h
@@ -45,9 +45,11 @@
 
   // Called in response to an AddChannelRequest. This means that a response has
   // been received from the remote server.
-  virtual void OnAddChannelResponse(const std::string& selected_subprotocol,
-                                    const std::string& extensions,
-                                    int64_t send_flow_control_quota) = 0;
+  virtual void OnAddChannelResponse(
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response,
+      const std::string& selected_subprotocol,
+      const std::string& extensions,
+      int64_t send_flow_control_quota) = 0;
 
   // Called when a data frame has been received from the remote host and needs
   // to be forwarded to the renderer process.
@@ -102,10 +104,6 @@
   virtual void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request) = 0;
 
-  // Called when the browser finishes the WebSocket Opening Handshake.
-  virtual void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) = 0;
-
   // Callbacks to be used in response to a call to OnSSLCertificateError. Very
   // similar to content::SSLErrorHandler::Delegate (which we can't use directly
   // due to layering constraints).
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc
index 3423b38..ef4f7a5 100644
--- a/net/websockets/websocket_handshake_stream_create_helper_test.cc
+++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -114,12 +114,12 @@
   ~TestConnectDelegate() override = default;
 
   void OnCreateRequest(URLRequest* request) override {}
-  void OnSuccess(std::unique_ptr<WebSocketStream> stream) override {}
+  void OnSuccess(
+      std::unique_ptr<WebSocketStream> stream,
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
   void OnFailure(const std::string& failure_message) override {}
   void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {}
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
   void OnSSLCertificateError(
       std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
           ssl_error_callbacks,
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc
index 99910c99b..30d1fee 100644
--- a/net/websockets/websocket_http2_handshake_stream.cc
+++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -332,7 +332,6 @@
   const int response_code = headers->response_code();
   switch (response_code) {
     case HTTP_OK:
-      OnFinishOpeningHandshake();
       return ValidateUpgradeResponse(headers);
 
     // We need to pass these through for authentication to work.
@@ -346,7 +345,6 @@
       OnFailure(base::StringPrintf(
           "Error during WebSocket handshake: Unexpected response code: %d",
           headers->response_code()));
-      OnFinishOpeningHandshake();
       result_ = HandshakeResult::HTTP2_INVALID_STATUS;
       return ERR_INVALID_RESPONSE;
   }
@@ -372,13 +370,6 @@
   return ERR_INVALID_RESPONSE;
 }
 
-void WebSocketHttp2HandshakeStream::OnFinishOpeningHandshake() {
-  DCHECK(http_response_info_);
-  WebSocketDispatchOnFinishOpeningHandshake(
-      connect_delegate_, request_info_->url, http_response_info_->headers,
-      http_response_info_->remote_endpoint, http_response_info_->response_time);
-}
-
 void WebSocketHttp2HandshakeStream::OnFailure(const std::string& message) {
   stream_request_->OnFailure(message);
 }
diff --git a/net/websockets/websocket_http2_handshake_stream.h b/net/websockets/websocket_http2_handshake_stream.h
index 23ab9d2..2e40191d 100644
--- a/net/websockets/websocket_http2_handshake_stream.h
+++ b/net/websockets/websocket_http2_handshake_stream.h
@@ -113,8 +113,6 @@
   // in which case returns OK, otherwise returns ERR_INVALID_RESPONSE.
   int ValidateUpgradeResponse(const HttpResponseHeaders* headers);
 
-  void OnFinishOpeningHandshake();
-
   void OnFailure(const std::string& message);
 
   HandshakeResult result_;
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc
index 5e2134a..0087486b6 100644
--- a/net/websockets/websocket_stream.cc
+++ b/net/websockets/websocket_stream.cc
@@ -204,7 +204,13 @@
     std::unique_ptr<URLRequest> url_request = std::move(url_request_);
     WebSocketHandshakeStreamBase* handshake_stream = handshake_stream_.get();
     handshake_stream_.reset();
-    connect_delegate_->OnSuccess(handshake_stream->Upgrade());
+    auto handshake_response_info =
+        std::make_unique<WebSocketHandshakeResponseInfo>(
+            url_request->url(), url_request->response_headers(),
+            url_request->GetResponseRemoteEndpoint(),
+            url_request->response_time());
+    connect_delegate_->OnSuccess(handshake_stream->Upgrade(),
+                                 std::move(handshake_response_info));
 
     // This is safe even if |this| has already been deleted.
     url_request->CancelWithError(ERR_WS_UPGRADE);
@@ -249,14 +255,6 @@
     connect_delegate_->OnFailure(failure_message);
   }
 
-  void OnFinishOpeningHandshake() {
-    WebSocketDispatchOnFinishOpeningHandshake(
-        connect_delegate(), url_request_->url(),
-        url_request_->response_headers(),
-        url_request_->GetResponseRemoteEndpoint(),
-        url_request_->response_time());
-  }
-
   WebSocketStream::ConnectDelegate* connect_delegate() const {
     return connect_delegate_.get();
   }
@@ -388,13 +386,11 @@
       return;
 
     case HTTP_UNAUTHORIZED:
-      owner_->OnFinishOpeningHandshake();
       owner_->ReportFailureWithMessage(
           "HTTP Authentication failed; no valid credentials available");
       return;
 
     case HTTP_PROXY_AUTHENTICATION_REQUIRED:
-      owner_->OnFinishOpeningHandshake();
       owner_->ReportFailureWithMessage("Proxy authentication failed");
       return;
 
@@ -506,18 +502,4 @@
   return std::move(request);
 }
 
-void WebSocketDispatchOnFinishOpeningHandshake(
-    WebSocketStream::ConnectDelegate* connect_delegate,
-    const GURL& url,
-    const scoped_refptr<HttpResponseHeaders>& headers,
-    const IPEndPoint& remote_endpoint,
-    base::Time response_time) {
-  DCHECK(connect_delegate);
-  if (headers.get()) {
-    connect_delegate->OnFinishOpeningHandshake(
-        std::make_unique<WebSocketHandshakeResponseInfo>(
-            url, headers, remote_endpoint, response_time));
-  }
-}
-
 }  // namespace net
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h
index 3bcb208..5d89951 100644
--- a/net/websockets/websocket_stream.h
+++ b/net/websockets/websocket_stream.h
@@ -98,7 +98,9 @@
 
     // Called on successful connection. The parameter is an object derived from
     // WebSocketStream.
-    virtual void OnSuccess(std::unique_ptr<WebSocketStream> stream) = 0;
+    virtual void OnSuccess(
+        std::unique_ptr<WebSocketStream> stream,
+        std::unique_ptr<WebSocketHandshakeResponseInfo> response) = 0;
 
     // Called on failure to connect.
     // |message| contains defails of the failure.
@@ -108,10 +110,6 @@
     virtual void OnStartOpeningHandshake(
         std::unique_ptr<WebSocketHandshakeRequestInfo> request) = 0;
 
-    // Called when the WebSocket Opening Handshake ends.
-    virtual void OnFinishOpeningHandshake(
-        std::unique_ptr<WebSocketHandshakeResponseInfo> response) = 0;
-
     // Called when there is an SSL certificate error. Should call
     // ssl_error_callbacks->ContinueSSLRequest() or
     // ssl_error_callbacks->CancelSSLRequest().
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc
index 49ed31b..65411a1 100644
--- a/net/websockets/websocket_stream_create_test_base.cc
+++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -34,7 +34,12 @@
     owner_->url_request_ = request;
   }
 
-  void OnSuccess(std::unique_ptr<WebSocketStream> stream) override {
+  void OnSuccess(
+      std::unique_ptr<WebSocketStream> stream,
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
+    if (owner_->response_info_)
+      ADD_FAILURE();
+    owner_->response_info_ = std::move(response);
     stream.swap(owner_->stream_);
     done_callback_.Run();
   }
@@ -52,13 +57,6 @@
     owner_->request_info_ = std::move(request);
   }
 
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
-    if (owner_->response_info_)
-      ADD_FAILURE();
-    owner_->response_info_ = std::move(response);
-  }
-
   void OnSSLCertificateError(
       std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
           ssl_error_callbacks,
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index af406b4..b3b7718 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -1464,7 +1464,7 @@
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("HTTP Authentication failed; no valid credentials available",
             failure_message());
-  EXPECT_TRUE(response_info_);
+  EXPECT_FALSE(response_info_);
 }
 
 TEST_P(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) {
@@ -1482,7 +1482,7 @@
                                 "Zm9vOmJheg==", kUnauthorizedResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
-  EXPECT_TRUE(response_info_);
+  EXPECT_FALSE(response_info_);
 }
 
 TEST_P(WebSocketStreamCreateBasicAuthTest, SuccessfulConnectionReuse) {
diff --git a/net/websockets/websocket_test_util.h b/net/websockets/websocket_test_util.h
index f6ef403..8ccc09f 100644
--- a/net/websockets/websocket_test_util.h
+++ b/net/websockets/websocket_test_util.h
@@ -184,12 +184,12 @@
   DummyConnectDelegate() = default;
   ~DummyConnectDelegate() override = default;
   void OnCreateRequest(URLRequest* url_request) override {}
-  void OnSuccess(std::unique_ptr<WebSocketStream> stream) override {}
+  void OnSuccess(
+      std::unique_ptr<WebSocketStream> stream,
+      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
   void OnFailure(const std::string& message) override {}
   void OnStartOpeningHandshake(
       std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {}
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
   void OnSSLCertificateError(
       std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
           ssl_error_callbacks,
diff --git a/remoting/android/BUILD.gn b/remoting/android/BUILD.gn
index 2fce66e..2e3cde9 100644
--- a/remoting/android/BUILD.gn
+++ b/remoting/android/BUILD.gn
@@ -43,9 +43,96 @@
 
 android_resources("remoting_android_client_java_resources") {
   custom_package = "org.chromium.chromoting"
-  resource_dirs = [ "java/res" ]
-  generated_resource_dirs = [ _raw_resources_base_dir ]
-  generated_resource_files = get_target_outputs(":credits_resources_raw")
+  sources = [
+    "java/res/drawable-hdpi/empty_host_list.png",
+    "java/res/drawable-hdpi/ic_action_full_screen.png",
+    "java/res/drawable-hdpi/ic_action_keyboard.png",
+    "java/res/drawable-hdpi/ic_announcement.png",
+    "java/res/drawable-hdpi/ic_help.png",
+    "java/res/drawable-hdpi/ic_host_offline.png",
+    "java/res/drawable-hdpi/ic_host_online.png",
+    "java/res/drawable-hdpi/ic_menu.png",
+    "java/res/drawable-hdpi/ic_mouse.png",
+    "java/res/drawable-hdpi/ic_refresh.png",
+    "java/res/drawable-hdpi/ic_touch.png",
+    "java/res/drawable-ldpi/empty_host_list.png",
+    "java/res/drawable-mdpi/empty_host_list.png",
+    "java/res/drawable-mdpi/ic_action_full_screen.png",
+    "java/res/drawable-mdpi/ic_action_keyboard.png",
+    "java/res/drawable-mdpi/ic_announcement.png",
+    "java/res/drawable-mdpi/ic_help.png",
+    "java/res/drawable-mdpi/ic_host_offline.png",
+    "java/res/drawable-mdpi/ic_host_online.png",
+    "java/res/drawable-mdpi/ic_menu.png",
+    "java/res/drawable-mdpi/ic_mouse.png",
+    "java/res/drawable-mdpi/ic_refresh.png",
+    "java/res/drawable-mdpi/ic_touch.png",
+    "java/res/drawable-xhdpi/empty_host_list.png",
+    "java/res/drawable-xhdpi/ic_action_full_screen.png",
+    "java/res/drawable-xhdpi/ic_action_keyboard.png",
+    "java/res/drawable-xhdpi/ic_announcement.png",
+    "java/res/drawable-xhdpi/ic_help.png",
+    "java/res/drawable-xhdpi/ic_host_offline.png",
+    "java/res/drawable-xhdpi/ic_host_online.png",
+    "java/res/drawable-xhdpi/ic_menu.png",
+    "java/res/drawable-xhdpi/ic_mouse.png",
+    "java/res/drawable-xhdpi/ic_refresh.png",
+    "java/res/drawable-xhdpi/ic_touch.png",
+    "java/res/drawable-xxhdpi/empty_host_list.png",
+    "java/res/drawable-xxhdpi/ic_action_full_screen.png",
+    "java/res/drawable-xxhdpi/ic_action_keyboard.png",
+    "java/res/drawable-xxhdpi/ic_announcement.png",
+    "java/res/drawable-xxhdpi/ic_help.png",
+    "java/res/drawable-xxhdpi/ic_host_offline.png",
+    "java/res/drawable-xxhdpi/ic_host_online.png",
+    "java/res/drawable-xxhdpi/ic_menu.png",
+    "java/res/drawable-xxhdpi/ic_mouse.png",
+    "java/res/drawable-xxhdpi/ic_refresh.png",
+    "java/res/drawable-xxhdpi/ic_touch.png",
+    "java/res/drawable-xxxhdpi/empty_host_list.png",
+    "java/res/drawable-xxxhdpi/ic_action_full_screen.png",
+    "java/res/drawable-xxxhdpi/ic_action_keyboard.png",
+    "java/res/drawable-xxxhdpi/ic_announcement.png",
+    "java/res/drawable-xxxhdpi/ic_help.png",
+    "java/res/drawable-xxxhdpi/ic_host_offline.png",
+    "java/res/drawable-xxxhdpi/ic_host_online.png",
+    "java/res/drawable-xxxhdpi/ic_menu.png",
+    "java/res/drawable-xxxhdpi/ic_mouse.png",
+    "java/res/drawable-xxxhdpi/ic_refresh.png",
+    "java/res/drawable-xxxhdpi/ic_touch.png",
+    "java/res/layout/account_ui.xml",
+    "java/res/layout/credits.xml",
+    "java/res/layout/desktop.xml",
+    "java/res/layout/help.xml",
+    "java/res/layout/host_offline.xml",
+    "java/res/layout/host_online.xml",
+    "java/res/layout/main.xml",
+    "java/res/layout/navigation_list.xml",
+    "java/res/layout/navigation_list_item.xml",
+    "java/res/layout/navigation_list_separator.xml",
+    "java/res/layout/notification_dialog.xml",
+    "java/res/layout/pin_dialog.xml",
+    "java/res/menu/chromoting_actionbar.xml",
+    "java/res/menu/desktop_actionbar.xml",
+    "java/res/menu/help_actionbar.xml",
+    "java/res/menu/host_context_menu.xml",
+    "java/res/mipmap-anydpi-v26/ic_launcher.xml",
+    "java/res/mipmap-hdpi/ic_launcher.png",
+    "java/res/mipmap-hdpi/ic_launcher_foreground.png",
+    "java/res/mipmap-mdpi/ic_launcher.png",
+    "java/res/mipmap-mdpi/ic_launcher_foreground.png",
+    "java/res/mipmap-xhdpi/ic_launcher.png",
+    "java/res/mipmap-xhdpi/ic_launcher_foreground.png",
+    "java/res/mipmap-xxhdpi/ic_launcher.png",
+    "java/res/mipmap-xxhdpi/ic_launcher_foreground.png",
+    "java/res/mipmap-xxxhdpi/ic_launcher.png",
+    "java/res/mipmap-xxxhdpi/ic_launcher_foreground.png",
+    "java/res/values-sw600dp/dimens.xml",
+    "java/res/values-v17/styles.xml",
+    "java/res/values/dimens.xml",
+    "java/res/values/ic_launcher_background.xml",
+  ]
+  sources += get_target_outputs(":credits_resources_raw")
   deps = [
     ":credits_resources_raw",
     "//remoting/resources:strings_java",
diff --git a/services/network/p2p/socket_udp.cc b/services/network/p2p/socket_udp.cc
index 392adab6..b6d6392 100644
--- a/services/network/p2p/socket_udp.cc
+++ b/services/network/p2p/socket_udp.cc
@@ -271,8 +271,8 @@
     }
   }
 
-  TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo",
-                               "size", packet.size);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("p2p", "UdpAsyncSendTo", packet.id, "size",
+                                    packet.size);
   // Don't try to set DSCP in following conditions,
   // 1. If the outgoing packet is set to DSCP_NO_CHANGE
   // 2. If no change in DSCP value from last packet
@@ -357,7 +357,8 @@
                                     int32_t transport_sequence_number,
                                     int64_t send_time_ms,
                                     int result) {
-  TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, "result", result);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("p2p", "UdpAsyncSendTo", packet_id);
+  TRACE_EVENT_NESTABLE_ASYNC_END1("p2p", "Send", packet_id, "result", result);
   if (result < 0) {
     ReportSocketError(result, "WebRTC.ICE.UdpSocketWriteErrorCode");
 
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index bcf29f6f..edfe0ca 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -31,12 +31,13 @@
       base::FEATURE_ENABLED_BY_DEFAULT
 };
 
-// Out of Blink CORS will be launched at m79. The flag will be enabled by
-// default around m81 after the feature rolled out over the finch successfully
-// at m79. Both mode will be maintained at least until m81, or around m83+ for
-// enterprise supports.
+// Out of Blink CORS for browsers is launched at m79 (http://crbug.com/1001450),
+// and one for WebView will be at m81 (http://crbug.com/1035763).
+// The legacy CORS will be also maintained at least until m81 for enterprise
+// users. See https://sites.google.com/a/chromium.org/dev/Home/loading/oor-cors
+// for FYI Builders information.
 const base::Feature kOutOfBlinkCors{"OutOfBlinkCors",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
+                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kReporting{"Reporting", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/services/network/websocket.cc b/services/network/websocket.cc
index 602dabc..28b247c3 100644
--- a/services/network/websocket.cc
+++ b/services/network/websocket.cc
@@ -72,6 +72,35 @@
   return static_cast<mojom::WebSocketMessageType>(opCode);
 }
 
+mojom::WebSocketHandshakeResponsePtr ToMojo(
+    std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
+    bool has_raw_headers_access) {
+  mojom::WebSocketHandshakeResponsePtr response_to_pass(
+      mojom::WebSocketHandshakeResponse::New());
+  response_to_pass->url.Swap(&response->url);
+  response_to_pass->status_code = response->headers->response_code();
+  response_to_pass->status_text = response->headers->GetStatusText();
+  response_to_pass->http_version = response->headers->GetHttpVersion();
+  response_to_pass->remote_endpoint = response->remote_endpoint;
+  size_t iter = 0;
+  std::string name, value;
+  std::string headers_text =
+      base::StrCat({response->headers->GetStatusLine(), "\r\n"});
+  while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
+    if (has_raw_headers_access ||
+        !net::HttpResponseHeaders::IsCookieResponseHeader(name)) {
+      // We drop cookie-related headers such as "set-cookie" when the
+      // renderer doesn't have access.
+      response_to_pass->headers.push_back(mojom::HttpHeader::New(name, value));
+      base::StrAppend(&headers_text, {name, ": ", value, "\r\n"});
+    }
+  }
+  headers_text.append("\r\n");
+  response_to_pass->headers_text = headers_text;
+
+  return response_to_pass;
+}
+
 }  // namespace
 
 // Implementation of net::WebSocketEventInterface. Receives events from our
@@ -85,10 +114,11 @@
   // net::WebSocketEventInterface implementation
 
   void OnCreateURLRequest(net::URLRequest* url_request) override;
-  // TODO(yoichio): Merge OnAddChannelResponse and OnFinishOpeningHandshake.
-  void OnAddChannelResponse(const std::string& selected_subprotocol,
-                            const std::string& extensions,
-                            int64_t send_flow_control_quota) override;
+  void OnAddChannelResponse(
+      std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
+      const std::string& selected_subprotocol,
+      const std::string& extensions,
+      int64_t send_flow_control_quota) override;
   void OnDataFrame(bool fin,
                    WebSocketMessageType type,
                    base::span<const char> payload) override;
@@ -101,8 +131,6 @@
   void OnFailChannel(const std::string& message) override;
   void OnStartOpeningHandshake(
       std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) override;
-  void OnFinishOpeningHandshake(
-      std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) override;
   void OnSSLCertificateError(
       std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
           callbacks,
@@ -120,8 +148,6 @@
  private:
   WebSocket* const impl_;
 
-  mojom::WebSocketHandshakeResponsePtr response_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
 };
 
@@ -143,6 +169,7 @@
 }
 
 void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
+    std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
     const std::string& selected_protocol,
     const std::string& extensions,
     int64_t send_flow_control_quota) {
@@ -184,11 +211,13 @@
       base::BindRepeating(&WebSocket::OnWritable, base::Unretained(impl_)));
   DCHECK_EQ(mojo_result, MOJO_RESULT_OK);
 
-  response_->selected_protocol = selected_protocol;
-  response_->extensions = extensions;
+  mojom::WebSocketHandshakeResponsePtr mojo_response =
+      ToMojo(std::move(response), !!impl_->has_raw_headers_access_);
+  mojo_response->selected_protocol = selected_protocol;
+  mojo_response->extensions = extensions;
   impl_->handshake_client_->OnConnectionEstablished(
       impl_->receiver_.BindNewPipeAndPassRemote(),
-      impl_->client_.BindNewPipeAndPassReceiver(), std::move(response_),
+      impl_->client_.BindNewPipeAndPassReceiver(), std::move(mojo_response),
       std::move(readable));
   impl_->receiver_.set_disconnect_handler(base::BindOnce(
       &WebSocket::OnConnectionError, base::Unretained(impl_), FROM_HERE));
@@ -289,38 +318,6 @@
       std::move(request_to_pass));
 }
 
-void WebSocket::WebSocketEventHandler::OnFinishOpeningHandshake(
-    std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) {
-  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
-           << reinterpret_cast<void*>(this)
-           << " CanReadRawCookies=" << impl_->has_raw_headers_access_;
-
-  mojom::WebSocketHandshakeResponsePtr response_to_pass(
-      mojom::WebSocketHandshakeResponse::New());
-  response_to_pass->url.Swap(&response->url);
-  response_to_pass->status_code = response->headers->response_code();
-  response_to_pass->status_text = response->headers->GetStatusText();
-  response_to_pass->http_version = response->headers->GetHttpVersion();
-  response_to_pass->remote_endpoint = response->remote_endpoint;
-  size_t iter = 0;
-  std::string name, value;
-  std::string headers_text =
-      base::StrCat({response->headers->GetStatusLine(), "\r\n"});
-  while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
-    if (impl_->has_raw_headers_access_ ||
-        !net::HttpResponseHeaders::IsCookieResponseHeader(name)) {
-      // We drop cookie-related headers such as "set-cookie" when the
-      // renderer doesn't have access.
-      response_to_pass->headers.push_back(mojom::HttpHeader::New(name, value));
-      base::StrAppend(&headers_text, {name, ": ", value, "\r\n"});
-    }
-  }
-  headers_text.append("\r\n");
-  response_to_pass->headers_text = headers_text;
-
-  response_ = std::move(response_to_pass);
-}
-
 void WebSocket::WebSocketEventHandler::OnSSLCertificateError(
     std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
     const GURL& url,
diff --git a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
index 5bbc4bf..2d4de082 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
+++ b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
@@ -44,7 +44,7 @@
     uintptr_t address = reinterpret_cast<uintptr_t>(pcs[i]);
     frames.emplace_back(address, module_cache_->GetModuleForAddress(address));
   }
-  profile_builder->OnSampleCompleted(std::move(frames));
+  profile_builder->OnSampleCompleted(std::move(frames), TRACE_TIME_TICKS_NOW());
 }
 
 }  // namespace tracing
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
index df1e197..1d4ca407 100644
--- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
+++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -210,12 +210,13 @@
 }
 
 void TracingSamplerProfiler::TracingProfileBuilder::OnSampleCompleted(
-    std::vector<base::Frame> frames) {
+    std::vector<base::Frame> frames,
+    base::TimeTicks sample_timestamp) {
   base::AutoLock l(trace_writer_lock_);
   if (!trace_writer_) {
     if (buffered_samples_.size() < kMaxBufferedSamples) {
       buffered_samples_.emplace_back(
-          BufferedSample(TRACE_TIME_TICKS_NOW(), std::move(frames)));
+          BufferedSample(sample_timestamp, std::move(frames)));
     }
     return;
   }
@@ -225,7 +226,7 @@
     }
     buffered_samples_.clear();
   }
-  WriteSampleToTrace(BufferedSample(TRACE_TIME_TICKS_NOW(), std::move(frames)));
+  WriteSampleToTrace(BufferedSample(sample_timestamp, std::move(frames)));
 }
 
 void TracingSamplerProfiler::TracingProfileBuilder::WriteSampleToTrace(
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
index 44dd230..6c0562e 100644
--- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
+++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
@@ -47,7 +47,8 @@
 
     // base::ProfileBuilder
     base::ModuleCache* GetModuleCache() override;
-    void OnSampleCompleted(std::vector<base::Frame> frames) override;
+    void OnSampleCompleted(std::vector<base::Frame> frames,
+                           base::TimeTicks sample_timestamp) override;
     void OnProfileCompleted(base::TimeDelta profile_duration,
                             base::TimeDelta sampling_period) override {}
 
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
index b05b55a8..4c89881 100644
--- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
+++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
@@ -358,14 +358,16 @@
   TracingSamplerProfiler::TracingProfileBuilder profile_builder(
       base::PlatformThreadId(),
       std::make_unique<MockTraceWriter>(base::DoNothing()), false);
-  profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)});
+  profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)},
+                                    base::TimeTicks());
 }
 
 TEST(TracingProfileBuilderTest, InvalidModule) {
   TracingSamplerProfiler::TracingProfileBuilder profile_builder(
       base::PlatformThreadId(),
       std::make_unique<MockTraceWriter>(base::DoNothing()), false);
-  profile_builder.OnSampleCompleted({base::Frame(0x1010, nullptr)});
+  profile_builder.OnSampleCompleted({base::Frame(0x1010, nullptr)},
+                                    base::TimeTicks());
 }
 
 #if defined(OS_ANDROID) || defined(OS_LINUX)
@@ -392,7 +394,8 @@
   auto* raw_trace_writer = trace_writer.get();
   TracingSamplerProfiler::TracingProfileBuilder profile_builder(
       base::PlatformThreadId(), std::move(trace_writer), false);
-  profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)});
+  profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)},
+                                    base::TimeTicks());
   raw_trace_writer->FlushPacketIfPossible();
   EXPECT_TRUE(found_build_id);
 }
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 3e63333..149013e 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -1,77 +1,11 @@
 {
   "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
   "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Android WebView P FYI (rel)": {
-    "isolated_scripts": [
-      {
-        "isolate_name": "chrome_public_wpt",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "chrome_public_wpt",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/chrome/test/chromedriver/cipd",
-              "location": "chrome/test/chromedriver/cipd",
-              "revision": "tLMjWvOcbQX4nMo5WnMsKWn0aaVludzuSX9yiVFUCoUC"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "expiration": 18000,
-          "hard_timeout": 14400,
-          "shards": 15
-        },
-        "test_target": "//chrome/android:chrome_public_wpt"
-      },
-      {
-        "isolate_name": "system_webview_wpt",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "system_webview_wpt",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/chrome/test/chromedriver/cipd",
-              "location": "chrome/test/chromedriver/cipd",
-              "revision": "tLMjWvOcbQX4nMo5WnMsKWn0aaVludzuSX9yiVFUCoUC"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "expiration": 18000,
-          "hard_timeout": 14400,
-          "shards": 15
-        },
-        "test_target": "//android_webview/test:system_webview_wpt"
-      }
-    ]
-  },
-  "Android WebView P OOR-CORS FYI (rel)": {
+  "Android WebView P Blink-CORS FYI (rel)": {
     "gtest_tests": [
       {
         "args": [
-          "--enable-features=OutOfBlinkCors",
+          "--disable-features=OutOfBlinkCors",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -118,7 +52,7 @@
       },
       {
         "args": [
-          "--enable-features=OutOfBlinkCors",
+          "--disable-features=OutOfBlinkCors",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -165,7 +99,7 @@
       },
       {
         "args": [
-          "--enable-features=OutOfBlinkCors",
+          "--disable-features=OutOfBlinkCors",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -218,7 +152,62 @@
       },
       {
         "args": [
-          "--enable-features=OutOfBlinkCors",
+          "--disable-field-trial-config",
+          "--disable-features=OutOfBlinkCors",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "webview_cts_tests_no_field_trial"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "webview_cts_tests_no_field_trial",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/android_webview/tools/cts_archive",
+              "location": "android_webview/tools/cts_archive",
+              "revision": "4kDr36wBuZtvbfaEin4U4oeFD7oAuN0flkWDImKBts4C"
+            },
+            {
+              "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"
+            }
+          ],
+          "shards": 2
+        },
+        "test": "webview_cts_tests",
+        "test_target": "//android_webview/test:webview_cts_tests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -266,7 +255,7 @@
       },
       {
         "args": [
-          "--enable-features=OutOfBlinkCors",
+          "--disable-features=OutOfBlinkCors",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -315,7 +304,7 @@
     "isolated_scripts": [
       {
         "args": [
-          "--enable-features=OutOfBlinkCors"
+          "--disable-features=OutOfBlinkCors"
         ],
         "isolate_name": "chrome_public_wpt",
         "merge": {
@@ -349,7 +338,7 @@
       },
       {
         "args": [
-          "--enable-features=OutOfBlinkCors"
+          "--disable-features=OutOfBlinkCors"
         ],
         "isolate_name": "system_webview_wpt",
         "merge": {
@@ -383,6 +372,72 @@
       }
     ]
   },
+  "Android WebView P FYI (rel)": {
+    "isolated_scripts": [
+      {
+        "isolate_name": "chrome_public_wpt",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "chrome_public_wpt",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/chrome/test/chromedriver/cipd",
+              "location": "chrome/test/chromedriver/cipd",
+              "revision": "tLMjWvOcbQX4nMo5WnMsKWn0aaVludzuSX9yiVFUCoUC"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "os": "Android"
+            }
+          ],
+          "expiration": 18000,
+          "hard_timeout": 14400,
+          "shards": 15
+        },
+        "test_target": "//chrome/android:chrome_public_wpt"
+      },
+      {
+        "isolate_name": "system_webview_wpt",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "system_webview_wpt",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/chrome/test/chromedriver/cipd",
+              "location": "chrome/test/chromedriver/cipd",
+              "revision": "tLMjWvOcbQX4nMo5WnMsKWn0aaVludzuSX9yiVFUCoUC"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "os": "Android"
+            }
+          ],
+          "expiration": 18000,
+          "hard_timeout": 14400,
+          "shards": 15
+        },
+        "test_target": "//android_webview/test:system_webview_wpt"
+      }
+    ]
+  },
   "android-bfcache-debug": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 58598d15..44331b19b 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -15464,6 +15464,180 @@
       }
     ]
   },
+  "linux-blink-cors-rel": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_blink_platform_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "blink_platform_unittests",
+        "test_target": "//third_party/blink/renderer/platform:blink_platform_unittests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "shards": 10
+        },
+        "test": "browser_tests",
+        "test_target": "//chrome/test:browser_tests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_content_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "content_browsertests",
+        "test_target": "//content/test:content_browsertests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_content_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "content_unittests",
+        "test_target": "//content/test:content_unittests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_extensions_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "extensions_browsertests",
+        "test_target": "//extensions:extensions_browsertests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_extensions_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "extensions_unittests",
+        "test_target": "//extensions:extensions_unittests"
+      },
+      {
+        "args": [
+          "--disable-features=OutOfBlinkCors"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "blink_cors_services_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "services_unittests",
+        "test_target": "//services:services_unittests"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--disable-features=OutOfBlinkCors",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors",
+          "--fuzzy-diff"
+        ],
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webkit_layout_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "shards": 12
+        },
+        "test_target": "//:blink_web_tests"
+      }
+    ]
+  },
   "linux-blink-heap-concurrent-marking-tsan-rel": {
     "gtest_tests": [
       {
@@ -17334,7 +17508,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 21
+          "shards": 50
         },
         "test": "browser_tests",
         "test_target": "//chrome/test:browser_tests"
@@ -17542,7 +17716,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 6
+          "shards": 12
         },
         "test": "content_browsertests",
         "test_target": "//content/test:content_browsertests"
@@ -17849,7 +18023,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 3
+          "shards": 10
         },
         "test": "interactive_ui_tests",
         "test_target": "//chrome/test:interactive_ui_tests"
@@ -18413,7 +18587,8 @@
             {
               "os": "Ubuntu-16.04"
             }
-          ]
+          ],
+          "shards": 4
         },
         "test": "sync_integration_tests",
         "test_target": "//chrome/test:sync_integration_tests"
@@ -20677,7 +20852,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 21
+          "shards": 50
         },
         "test": "browser_tests",
         "test_target": "//chrome/test:browser_tests"
@@ -20851,7 +21026,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 6
+          "shards": 12
         },
         "test": "content_browsertests",
         "test_target": "//content/test:content_browsertests"
@@ -21231,7 +21406,7 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "shards": 3
+          "shards": 10
         },
         "test": "interactive_ui_tests",
         "test_target": "//chrome/test:interactive_ui_tests"
@@ -21724,7 +21899,8 @@
             {
               "os": "Ubuntu-16.04"
             }
-          ]
+          ],
+          "shards": 4
         },
         "test": "sync_integration_tests",
         "test_target": "//chrome/test:sync_integration_tests"
@@ -22406,180 +22582,6 @@
       }
     ]
   },
-  "linux-oor-cors-rel": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_blink_platform_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "blink_platform_unittests",
-        "test_target": "//third_party/blink/renderer/platform:blink_platform_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "shards": 10
-        },
-        "test": "browser_tests",
-        "test_target": "//chrome/test:browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "content_browsertests",
-        "test_target": "//content/test:content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "content_unittests",
-        "test_target": "//content/test:content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "extensions_browsertests",
-        "test_target": "//extensions:extensions_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_extensions_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "extensions_unittests",
-        "test_target": "//extensions:extensions_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=OutOfBlinkCors"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "oor_cors_services_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "services_unittests",
-        "test_target": "//services:services_unittests"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--num-retries=3",
-          "--additional-driver-flag=--enable-features=OutOfBlinkCors",
-          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=OutOfBlinkCors",
-          "--fuzzy-diff"
-        ],
-        "isolate_name": "blink_web_tests",
-        "merge": {
-          "args": [
-            "--verbose"
-          ],
-          "script": "//third_party/blink/tools/merge_web_test_results.py"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "shards": 12
-        },
-        "test_target": "//:blink_web_tests"
-      }
-    ]
-  },
   "linux-wpt-fyi-rel": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 697a5b1..00cf5e4 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -144,6 +144,200 @@
     "isolated_scripts": [
       {
         "args": [
+          "--gtest-benchmark-name",
+          "angle_perftests"
+        ],
+        "isolate_name": "angle_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "angle_perftests",
+        "override_compile_targets": [
+          "angle_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-23.21.13.8792",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "load_library_perf_tests"
+        ],
+        "isolate_name": "load_library_perf_tests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "load_library_perf_tests",
+        "override_compile_targets": [
+          "load_library_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-23.21.13.8792",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "media_perftests"
+        ],
+        "isolate_name": "media_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "media_perftests",
+        "override_compile_targets": [
+          "media_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-23.21.13.8792",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "passthrough_command_buffer_perftests",
+          "--use-cmd-decoder=passthrough",
+          "--use-angle=gl-null"
+        ],
+        "isolate_name": "command_buffer_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "passthrough_command_buffer_perftests",
+        "override_compile_targets": [
+          "command_buffer_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-23.21.13.8792",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "validating_command_buffer_perftests",
+          "--use-cmd-decoder=validating",
+          "--use-stub"
+        ],
+        "isolate_name": "command_buffer_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "validating_command_buffer_perftests",
+        "override_compile_targets": [
+          "command_buffer_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-23.21.13.8792",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
           "-v",
           "--browser=release_x64",
           "--upload-results",
@@ -190,6 +384,120 @@
     "isolated_scripts": [
       {
         "args": [
+          "--gtest-benchmark-name",
+          "components_perftests"
+        ],
+        "isolate_name": "components_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "components_perftests",
+        "override_compile_targets": [
+          "components_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "102b:0532-6.1.7600.16385",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R210 II (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "load_library_perf_tests"
+        ],
+        "isolate_name": "load_library_perf_tests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "load_library_perf_tests",
+        "override_compile_targets": [
+          "load_library_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "102b:0532-6.1.7600.16385",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R210 II (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "media_perftests"
+        ],
+        "isolate_name": "media_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "media_perftests",
+        "override_compile_targets": [
+          "media_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "102b:0532-6.1.7600.16385",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "PowerEdge R210 II (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
           "-v",
           "--browser=release",
           "--upload-results",
@@ -528,46 +836,6 @@
       {
         "args": [
           "--gtest-benchmark-name",
-          "angle_perftests",
-          "--shard-timeout=300"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "override_compile_targets": [
-          "angle_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 7200,
-          "hard_timeout": 19800,
-          "ignore_task_failure": false,
-          "io_timeout": 19800,
-          "shards": 1
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "requires_simultaneous_shard_dispatch": true,
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--gtest-benchmark-name",
           "base_perftests"
         ],
         "isolate_name": "base_perftests",
@@ -1574,6 +1842,236 @@
     "isolated_scripts": [
       {
         "args": [
+          "--gtest-benchmark-name",
+          "angle_perftests",
+          "--shard-timeout=300"
+        ],
+        "isolate_name": "angle_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "angle_perftests",
+        "override_compile_targets": [
+          "angle_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "base_perftests"
+        ],
+        "isolate_name": "base_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "base_perftests",
+        "override_compile_targets": [
+          "base_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "components_perftests"
+        ],
+        "isolate_name": "components_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "components_perftests",
+        "override_compile_targets": [
+          "components_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "dawn_perf_tests",
+          "--shard-timeout=300"
+        ],
+        "isolate_name": "dawn_perf_tests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "dawn_perf_tests",
+        "override_compile_targets": [
+          "dawn_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "media_perftests"
+        ],
+        "isolate_name": "media_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "media_perftests",
+        "override_compile_targets": [
+          "media_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--gtest-benchmark-name",
+          "views_perftests"
+        ],
+        "isolate_name": "views_perftests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "views_perftests",
+        "override_compile_targets": [
+          "views_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-23.20.16.4877",
+              "os": "Windows-10-16299.309",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
           "-v",
           "--browser=release_x64",
           "--upload-results",
diff --git a/testing/buildbot/filters/android.pie_arm64_rel.chrome_public_test_apk.filter b/testing/buildbot/filters/android.pie_arm64_rel.chrome_public_test_apk.filter
index b396d40..5793ede 100644
--- a/testing/buildbot/filters/android.pie_arm64_rel.chrome_public_test_apk.filter
+++ b/testing/buildbot/filters/android.pie_arm64_rel.chrome_public_test_apk.filter
@@ -1,52 +1,70 @@
--org.chromium.chrome.browser.autofill_assistant.AutofillAssistantGenericUiTest.testStaticUserInterface
+# crbug/1033877
+-org.chromium.chrome.browser.autofill_assistant.AutofillAssistantDirectActionHandlerTest.testReportAvailableDirectActions
+
+# crbug/1036413
 -org.chromium.chrome.browser.banners.AppBannerManagerTest.testBlockedAmbientBadgeDoesNotAppearAgainForMonths
--org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.testDictionaryDefinitions
--org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.testTapALot
--org.chromium.chrome.browser.directactions.DirectActionAvailabilityWebappTest.testCoreDirectActionInWebappActivity
+
+# crbug/1036417
 -org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsTest.testSingleObserverFontFamily
 -org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsTest.testSingleObserverFontScaling
 -org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsTest.testSingleObserverTheme
+
+# crbug/963898
 -org.chromium.chrome.browser.download.DownloadMediaParserTest.testParseVideoH264
+
+# crbug/1018181
 -org.chromium.chrome.browser.download.home.DownloadActivityV2Test.testLaunchingActivity
+
+# crbug/1032118
 -org.chromium.chrome.browser.notifications.channels.ChannelsInitializerTest.testEnsureInitialized_permissionRequests
 -org.chromium.chrome.browser.notifications.channels.ChannelsInitializerTest.testEnsureInitialized_permissionRequestsHigh
 -org.chromium.chrome.browser.notifications.StandardNotificationBuilderTest.testSetAll
+
+# crbug/1036459
 -org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerViewTest.testDismissArticleWithContextMenu
 -org.chromium.chrome.browser.ntp.NewTabPageTest.testFocusFakebox
 -org.chromium.chrome.browser.ntp.NewTabPageTest.testOpenMostVisitedItemInIncognitoTab
 -org.chromium.chrome.browser.ntp.NewTabPageTest.testRemoveMostVisitedItem
 -org.chromium.chrome.browser.ntp.RecentTabsPageTest.testRecentlyClosedTabs
+
+# crbug/1035956
+-org.chromium.chrome.browser.payments.PaymentRequestNoShippingTest.testSaveNewCardAndNewBillingAddressAndPay
+-org.chromium.chrome.browser.payments.PaymentRequestRemoveBillingAddressTest.testPayWithCard
 -org.chromium.chrome.browser.payments.PaymentRequestRetryTest.testRetryWithShippingAddressErrorsAndPayerErrors
+
+# crbug/707528
 -org.chromium.chrome.browser.push_messaging.PushMessagingTest.testPushAndShowNotification
+
+# crbug/836460
 -org.chromium.chrome.browser.settings.autofill.AutofillProfilesFragmentTest.testKeyboardShownOnDpadCenter
--org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testBarcodeDetection
--org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testTextDetection
+
+# crbug/1036532
 -org.chromium.chrome.browser.signin.SigninTest.testConsumerSignin
+
+# crbug/1036545
 -org.chromium.chrome.browser.suggestions.tile.TileGroupTest.testDismissTileUndo
 -org.chromium.chrome.browser.suggestions.tile.TileGroupTest.testDismissTileWithContextMenu
+
+# crbug/1036551
 -org.chromium.chrome.browser.tabmodel.TabModelMergingTest.testMergeOnColdStartIntoChromeTabbedActivity2
+
+# crbug/1017141
+-org.chromium.chrome.browser.tasks.tab_management.TabSwitcherMultiWindowTest.testMoveTabsAcrossWindow_GTS_WithoutGroup
+
+# crbug/1036552
 -org.chromium.chrome.browser.tasks.tab_management.TabGridDialogParentTest.testDialog_ZoomInFadeOut
 -org.chromium.chrome.browser.tasks.tab_management.TabGridDialogParentTest.testDialog_ZoomInZoomOut
--org.chromium.chrome.browser.tasks.tab_management.TabSwitcherMultiWindowTest.testMoveTabsAcrossWindow_GTS_WithoutGroup
+
+# crbug/1036553
 -org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTabMenuDismissedOnOrientationChange
 -org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarAppears
 -org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarOverflowMenus
 -org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarReopenOnTarget
+
+# crbug/1036556
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testMediaSuspension
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testMultiWindow
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testTabAddedFromCustomTab
--org.chromium.chrome.browser.webapps.WebApkActivityTest.testActivateWebApkLPlus
--org.chromium.chrome.features.start_surface.StartSurfaceLayoutTest.testRenderGrid_10WebTabs
--org.chromium.chrome.features.start_surface.StartSurfaceLayoutTest.testRenderGrid_Incognito
--org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithHint
--org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithoutHint
--org.chromium.shape_detection.FaceDetectionImplTest.testDetectFacesInProfileWithGmsCore
--org.chromium.shape_detection.FaceDetectionImplTest.testDetectRotatedFaceWithGmsCore
--org.chromium.shape_detection.FaceDetectionImplTest.testDetectValidImageWithGmsCore
--org.chromium.shape_detection.TextDetectionImplTest.testDetectSucceedsOnValidBitmap
--org.chromium.chrome.browser.autofill_assistant.AutofillAssistantDirectActionHandlerTest.testReportAvailableDirectActions
--org.chromium.chrome.browser.media.ui.PictureInPictureControllerTest.testEnterPip
--org.chromium.chrome.browser.media.ui.PictureInPictureControllerTest.testReenterPip
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testEagerSuspension
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testNavigateToSuspended
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testNavigateToSuspendedDomain_differentPage
@@ -56,3 +74,21 @@
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testTabAddedInBackground
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testTabSwitchBackToSuspended
 -org.chromium.chrome.browser.usage_stats.TabSuspensionTest.testTabUnsuspendedInBackground
+
+# crbug/1023833
+-org.chromium.chrome.features.start_surface.StartSurfaceLayoutTest.testRenderGrid_10WebTabs
+-org.chromium.chrome.features.start_surface.StartSurfaceLayoutTest.testRenderGrid_Incognito
+
+# crbug/1036571
+-org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithHint
+-org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithoutHint
+-org.chromium.shape_detection.FaceDetectionImplTest.testDetectFacesInProfileWithGmsCore
+-org.chromium.shape_detection.FaceDetectionImplTest.testDetectRotatedFaceWithGmsCore
+-org.chromium.shape_detection.FaceDetectionImplTest.testDetectValidImageWithGmsCore
+-org.chromium.shape_detection.TextDetectionImplTest.testDetectSucceedsOnValidBitmap
+-org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testBarcodeDetection
+-org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testTextDetection
+
+# crbug/1034412
+-org.chromium.chrome.browser.media.ui.PictureInPictureControllerTest.testEnterPip
+-org.chromium.chrome.browser.media.ui.PictureInPictureControllerTest.testReenterPip
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index d9d7cf2..222db2c7 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -106,12 +106,12 @@
       # chromium.fyi
       'linux-code-coverage': {
         'swarming': {
-          'shards': 21,
+          'shards': 50,
         },
       },
       'linux-chromeos-code-coverage': {
         'swarming': {
-          'shards': 21,
+          'shards': 50,
         },
       },
       'mac-code-coverage': {
@@ -556,6 +556,17 @@
           'shards': 3,
         },
       },
+      # chromium.fyi
+      'linux-code-coverage': {
+        'swarming': {
+          'shards': 12,
+        },
+      },
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 12,
+        },
+      },
     },
   },
   'content_shell_crash_test': {
@@ -903,6 +914,17 @@
           '--gtest_filter=-SadTabViewInteractiveUITest.ReloadMultipleSadTabs',
         ],
       },
+      # chromium.fyi
+      'linux-code-coverage': {
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 10,
+        },
+      },
     },
   },
   'ipc_tests': {
@@ -1571,6 +1593,17 @@
       'Win10 Tests x64 (dbg)': {
         'experiment_percentage': 100, # https://crbug.com/840369
       },
+      # chromium.fyi
+      'linux-code-coverage': {
+        'swarming': {
+          'shards': 4,
+        },
+      },
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 4,
+        },
+      },
     },
   },
   'tab_capture_end2end_tests': {
@@ -1940,6 +1973,13 @@
           '--fuzzy-diff',
         ],
       },
+      'linux-blink-cors-rel': {
+        'args': [
+          '--additional-driver-flag=--disable-features=OutOfBlinkCors',
+          '--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors',
+          '--fuzzy-diff',
+        ],
+      },
       'linux-blink-heap-concurrent-marking-tsan-rel': {
         'args': [
           '--release',
@@ -1952,13 +1992,6 @@
           '--fuzzy-diff',
         ],
       },
-      'linux-oor-cors-rel': {
-        'args': [
-          '--additional-driver-flag=--enable-features=OutOfBlinkCors',
-          '--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=OutOfBlinkCors',
-          '--fuzzy-diff',
-        ],
-      },
       'mac10.10-blink-rel-dummy': {
         'swarming': {
           'shards': 20,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index dec904c..f45fd91 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -284,6 +284,54 @@
       },
     },
 
+    'blink_cors_gtests': {
+      'blink_cors_blink_platform_unittests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'blink_platform_unittests'
+      },
+      'blink_cors_browser_tests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+        'test': 'browser_tests'
+      },
+      'blink_cors_content_browsertests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'content_browsertests'
+      },
+      'blink_cors_content_unittests' : {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'content_unittests'
+      },
+      'blink_cors_extensions_browsertests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'extensions_browsertests'
+      },
+      'blink_cors_extensions_unittests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'extensions_unittests'
+      },
+      'blink_cors_services_unittests': {
+        'args': [
+          '--disable-features=OutOfBlinkCors'
+        ],
+        'test': 'services_unittests'
+      }
+    },
+
     'cast_audio_specific_chromium_gtests': {
       'cast_audio_backend_unittests': {},
       'cast_base_unittests': {},
@@ -2860,54 +2908,6 @@
       'views_unittests': {},
     },
 
-    'oor_cors_gtests': {
-      'oor_cors_blink_platform_unittests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'blink_platform_unittests'
-      },
-      'oor_cors_browser_tests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'swarming': {
-          'shards': 10,
-        },
-        'test': 'browser_tests'
-      },
-      'oor_cors_content_browsertests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'content_browsertests'
-      },
-      'oor_cors_content_unittests' : {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'content_unittests'
-      },
-      'oor_cors_extensions_browsertests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'extensions_browsertests'
-      },
-      'oor_cors_extensions_unittests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'extensions_unittests'
-      },
-      'oor_cors_services_unittests': {
-        'args': [
-          '--enable-features=OutOfBlinkCors'
-        ],
-        'test': 'services_unittests'
-      }
-    },
-
     'opus_tests': {
       'opus_tests': {
         'args': [
@@ -4248,11 +4248,12 @@
       'webview_ui_instrumentation_tests_no_field_trial',
     ],
 
-    'webview_bot_oor_cors_gtests': [
+    'webview_bot_blink_cors_gtests': [
       'system_webview_shell_instrumentation_tests',
       'webview_bot_instrumentation_test_apk_gtest',
       'webview_bot_unittests_gtest',
       'webview_cts_tests_gtest',
+      'webview_cts_tests_gtest_no_field_trial',
       'webview_ui_instrumentation_tests',
     ],
 
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index c9237e1..4a0946fd 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -664,6 +664,21 @@
   {
     'name': 'chromium.android.fyi',
     'machines': {
+      'Android WebView P Blink-CORS FYI (rel)': {
+        'mixins': [
+          'pie_fleet',
+          'walleye',
+        ],
+        'test_suites': {
+          'gtest_tests': 'webview_bot_blink_cors_gtests',
+          'isolated_scripts': 'android_wpt_scripts',
+        },
+        'args': [
+          '--disable-features=OutOfBlinkCors',
+        ],
+        'use_swarming': True,
+        'os_type': 'android',
+      },
       'Android WebView P FYI (rel)': {
         'mixins': [
           'pie_fleet',
@@ -675,21 +690,6 @@
         'use_swarming': True,
         'os_type': 'android',
       },
-      'Android WebView P OOR-CORS FYI (rel)': {
-        'mixins': [
-          'pie_fleet',
-          'walleye',
-        ],
-        'test_suites': {
-          'gtest_tests': 'webview_bot_oor_cors_gtests',
-          'isolated_scripts': 'android_wpt_scripts',
-        },
-        'args': [
-          '--enable-features=OutOfBlinkCors',
-        ],
-        'use_swarming': True,
-        'os_type': 'android',
-      },
       'android-bfcache-debug': {
         'mixins': [
           'kitkat',
@@ -1842,6 +1842,15 @@
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
         },
       },
+      'linux-blink-cors-rel': {
+        'mixins': [
+          'linux-xenial'
+        ],
+        'test_suites': {
+          'gtest_tests': 'blink_cors_gtests',
+          'isolated_scripts': 'chromium_webkit_isolated_scripts'
+        }
+      },
       'linux-blink-heap-concurrent-marking-tsan-rel': {
         'mixins': [
           'linux-xenial',
@@ -1918,15 +1927,6 @@
           'gtest_tests': 'fieldtrial_browser_tests',
         },
       },
-      'linux-oor-cors-rel': {
-        'mixins': [
-          'linux-xenial'
-        ],
-        'test_suites': {
-          'gtest_tests': 'oor_cors_gtests',
-          'isolated_scripts': 'chromium_webkit_isolated_scripts'
-        }
-      },
       'linux-wpt-fyi-rel': {
         'mixins': [
           'linux-xenial',
diff --git a/third_party/android_deps/.gitignore b/third_party/android_deps/.gitignore
index 73fc9f1..7afb8345 100644
--- a/third_party/android_deps/.gitignore
+++ b/third_party/android_deps/.gitignore
@@ -1,3 +1,10 @@
+.gradle/
+.idea/
+.settings/
+local.properties
+buildSrc/.gradle/
+buildSrc/build/
+
 # JAR and AAR files will be fetched via CIPD.
 libs/*/*.jar
 libs/*/*.aar
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index 1cde18287..89e0837099 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -1200,7 +1200,7 @@
   supports_android = true
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1213,7 +1213,7 @@
   info_path = "libs/android_arch_core_runtime/android_arch_core_runtime.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":android_arch_core_common_java",
@@ -1227,7 +1227,7 @@
   info_path = "libs/android_arch_lifecycle_livedata/android_arch_lifecycle_livedata.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":android_arch_core_common_java",
@@ -1242,7 +1242,7 @@
   info_path = "libs/android_arch_lifecycle_livedata_core/android_arch_lifecycle_livedata_core.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":android_arch_core_common_java",
@@ -1258,7 +1258,7 @@
   supports_android = true
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1271,7 +1271,7 @@
   info_path = "libs/androidx_arch_core_core_runtime/androidx_arch_core_core_runtime.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1285,7 +1285,7 @@
   info_path = "libs/androidx_cursoradapter_cursoradapter/androidx_cursoradapter_cursoradapter.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1298,7 +1298,7 @@
   info_path = "libs/androidx_documentfile_documentfile/androidx_documentfile_documentfile.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1311,7 +1311,7 @@
   info_path = "libs/androidx_fragment_fragment/androidx_fragment_fragment.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1329,7 +1329,7 @@
   info_path = "libs/androidx_leanback_leanback/androidx_leanback_leanback.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_core_core_java",
@@ -1346,7 +1346,7 @@
   info_path = "libs/androidx_legacy_legacy_preference_v14/androidx_legacy_legacy_preference_v14.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_preference_preference_java",
@@ -1360,7 +1360,7 @@
   info_path = "libs/androidx_lifecycle_lifecycle_livedata/androidx_lifecycle_lifecycle_livedata.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_arch_core_core_common_java",
@@ -1375,7 +1375,7 @@
   info_path = "libs/androidx_lifecycle_lifecycle_livedata_core/androidx_lifecycle_lifecycle_livedata_core.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_arch_core_core_common_java",
@@ -1390,7 +1390,7 @@
   info_path = "libs/androidx_loader_loader/androidx_loader_loader.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1406,7 +1406,7 @@
   info_path = "libs/androidx_media_media/androidx_media_media.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1422,7 +1422,7 @@
   info_path = "libs/androidx_palette_palette/androidx_palette_palette.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_core_core_java",
@@ -1436,7 +1436,7 @@
   info_path = "libs/androidx_print_print/androidx_print_print.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1449,7 +1449,7 @@
   info_path = "libs/androidx_slidingpanelayout_slidingpanelayout/androidx_slidingpanelayout_slidingpanelayout.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1465,7 +1465,7 @@
       "libs/androidx_transition_transition/androidx_transition_transition.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1481,7 +1481,7 @@
   info_path = "libs/androidx_vectordrawable_vectordrawable/androidx_vectordrawable_vectordrawable.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1496,7 +1496,7 @@
   info_path = "libs/androidx_vectordrawable_vectordrawable_animated/androidx_vectordrawable_vectordrawable_animated.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_legacy_legacy_support_core_ui_java",
@@ -1510,7 +1510,7 @@
   info_path = "libs/androidx_versionedparcelable_versionedparcelable/androidx_versionedparcelable_versionedparcelable.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":androidx_annotation_annotation_java",
@@ -1525,7 +1525,7 @@
   info_path = "libs/com_android_support_animated_vector_drawable/com_android_support_animated_vector_drawable.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_core_ui_java",
@@ -1539,7 +1539,7 @@
   info_path = "libs/com_android_support_cursoradapter/com_android_support_cursoradapter.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1552,7 +1552,7 @@
   info_path = "libs/com_android_support_documentfile/com_android_support_documentfile.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1565,7 +1565,7 @@
   info_path = "libs/com_android_support_leanback_v17/com_android_support_leanback_v17.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_recyclerview_v7_java",
@@ -1582,7 +1582,7 @@
   info_path = "libs/com_android_support_loader/com_android_support_loader.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":android_arch_lifecycle_livedata_java",
@@ -1599,7 +1599,7 @@
       "libs/com_android_support_palette_v7/com_android_support_palette_v7.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_compat_java",
@@ -1613,7 +1613,7 @@
   info_path = "libs/com_android_support_preference_v14/com_android_support_preference_v14.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_preference_v7_java",
@@ -1626,7 +1626,7 @@
   info_path = "libs/com_android_support_print/com_android_support_print.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1640,7 +1640,7 @@
   info_path = "libs/com_android_support_slidingpanelayout/com_android_support_slidingpanelayout.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_customview_java",
@@ -1655,7 +1655,7 @@
   info_path = "libs/com_android_support_support_media_compat/com_android_support_support_media_compat.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1671,7 +1671,7 @@
   info_path = "libs/com_android_support_support_vector_drawable/com_android_support_support_vector_drawable.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1687,7 +1687,7 @@
       "libs/com_android_support_transition/com_android_support_transition.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_support_annotations_java",
@@ -1702,7 +1702,7 @@
   info_path = "libs/com_android_support_versionedparcelable/com_android_support_versionedparcelable.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_android_support_collections_java",
@@ -1718,7 +1718,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1729,7 +1729,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1739,7 +1739,7 @@
   info_path = "libs/com_google_android_gms_play_services_clearcut/com_google_android_gms_play_services_clearcut.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":google_play_services_base_java",
@@ -1758,7 +1758,7 @@
   info_path = "libs/com_google_android_gms_play_services_flags/com_google_android_gms_play_services_flags.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":google_play_services_base_java",
@@ -1775,7 +1775,7 @@
   info_path = "libs/com_google_android_gms_play_services_phenotype/com_google_android_gms_play_services_phenotype.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":google_play_services_base_java",
@@ -1793,7 +1793,7 @@
   info_path = "libs/com_google_android_gms_play_services_places_placereport/com_google_android_gms_play_services_places_placereport.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":google_play_services_basement_java",
@@ -1809,7 +1809,7 @@
   info_path = "libs/com_google_android_gms_play_services_stats/com_google_android_gms_play_services_stats.info"
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":google_play_services_basement_java",
@@ -1826,7 +1826,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_google_guava_guava_java",
@@ -1841,7 +1841,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1852,7 +1852,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1863,7 +1863,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_google_dagger_dagger_java",
@@ -1880,7 +1880,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_google_dagger_dagger_java",
@@ -1897,7 +1897,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_google_guava_guava_java",
@@ -1911,7 +1911,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1922,7 +1922,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_github_kevinstern_software_and_algorithms_java",
@@ -1942,7 +1942,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1953,7 +1953,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1965,7 +1965,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -1976,7 +1976,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":com_google_errorprone_javac_shaded_java",
@@ -1991,7 +1991,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2003,7 +2003,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2014,7 +2014,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2025,7 +2025,7 @@
   supports_android = true
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   testonly = true
 
@@ -2040,7 +2040,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2051,7 +2051,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2062,7 +2062,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":org_checkerframework_checker_qual_java",
@@ -2077,7 +2077,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
   deps = [
     ":org_checkerframework_checker_qual_java",
@@ -2091,7 +2091,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 
@@ -2102,7 +2102,7 @@
   enable_bytecode_rewriter = false
 
   # To remove visibility constraint, add this dependency to
-  # //tools/android/roll/android_deps/build.gradle.
+  # //third_party/android_deps/build.gradle.
   visibility = [ ":*" ]
 }
 # === Generated Code End ===
diff --git a/third_party/android_deps/README.chromium b/third_party/android_deps/README.chromium
index 6e2d17c..5e6727be 100644
--- a/third_party/android_deps/README.chromium
+++ b/third_party/android_deps/README.chromium
@@ -1,6 +1,6 @@
 Name: Android Deps Repository
 Short Name: android_deps
-URL: https://chromium.googlesource.com/chromium/src/+/master/tools/android/roll/android_deps/README.md
+URL: https://chromium.googlesource.com/chromium/src/+/master/third_party/android_deps/README.md
 Version: 1
 License: Refer to additional_readme_paths.json
 License Android Compatible: yes
@@ -35,4 +35,4 @@
 ```
 
 Instructions for adding/updating dependencies are in:
-    //tools/android/roll/android_deps/README.md
+    //third_party/android_deps/README.md
diff --git a/tools/android/roll/android_deps/README.md b/third_party/android_deps/README.md
similarity index 92%
rename from tools/android/roll/android_deps/README.md
rename to third_party/android_deps/README.md
index 9b57388d..6ac64c4d9 100644
--- a/tools/android/roll/android_deps/README.md
+++ b/third_party/android_deps/README.md
@@ -38,7 +38,7 @@
       problems. The cipd commands output by `fetch_all.py --update-all` already
       check for uniqueness of the tag before uploading a new version. You can
       also supply a new suffix in your package using FALLBACK_PROPERTIES in
-      tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.goovy
+      third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.goovy
 
 4. Run the commands printed at step 3 to create new and updated packages
    via cipd.
@@ -51,7 +51,7 @@
 
 5. Thoroughly test your change on a clean checkout.
     - Run the following command:
-      `rm -rf third_party/android_deps/libs/[!O]* && tools/android/roll/android_deps/fetch_all.py --update-all`.
+      `rm -rf third_party/android_deps/libs/[!O]* && third_party/android_deps/fetch_all.py --update-all`.
     - This ensures that all your deps are fresh. You do not need to run the
       commands printed out in this step.
 
@@ -74,7 +74,7 @@
 [owners_link]: http://go/android-deps-owners
 [docs_link]: ../../../../docs/adding_to_third_party.md
 [android_sdk_link]: https://developer.android.com/studio/terms
-[readme_chromium_link]: ../../../../third_party/android_deps/README.chromium
+[readme_chromium_link]: third_party/android_deps/README.chromium
 
 ### Implementation notes:
 The script invokes a Gradle plugin to leverage its dependency resolution
diff --git a/tools/android/roll/android_deps/build.gradle b/third_party/android_deps/build.gradle
similarity index 99%
rename from tools/android/roll/android_deps/build.gradle
rename to third_party/android_deps/build.gradle
index d395770..7535791 100644
--- a/tools/android/roll/android_deps/build.gradle
+++ b/third_party/android_deps/build.gradle
@@ -151,7 +151,7 @@
     // Paths are relative to the chromium source root.
     repositoryPath 'third_party/android_deps'
     depsPath 'DEPS'
-    chromiumSourceRoot '../../../..'
+    chromiumSourceRoot '../..'
     cipdBucket 'chromium'
 }
 
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
similarity index 98%
rename from tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
rename to third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
index de6dc2d..63b39843 100644
--- a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
+++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -207,7 +207,7 @@
 
             if (!dependency.visible) {
               sb.append("  # To remove visibility constraint, add this dependency to\n")
-              sb.append("  # //tools/android/roll/android_deps/build.gradle.\n")
+              sb.append("  # //third_party/android_deps/build.gradle.\n")
               sb.append("  visibility = [ \":*\" ]\n")
             }
             if (dependency.testOnly) sb.append("  testonly = true\n")
@@ -355,7 +355,7 @@
         def sb = new StringBuilder()
         // Note: The string we're inserting is nested 1 level, hence the 2 leading spaces. Same
         // applies to the multiline package declaration string below.
-        sb.append("  # Generated by //tools/android/roll/android_deps/fetch_all.py")
+        sb.append("  # Generated by //third_party/android_deps/fetch_all.py")
 
         // Comparator to sort the dependencies in alphabetical order.
         def dependencyComparator = { dependency1, dependency2 ->
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
similarity index 100%
rename from tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
rename to third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
similarity index 100%
rename from tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
rename to third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
diff --git a/tools/android/roll/android_deps/fetch_all.py b/third_party/android_deps/fetch_all.py
similarity index 89%
rename from tools/android/roll/android_deps/fetch_all.py
rename to third_party/android_deps/fetch_all.py
index 49f65a6d..640ab103 100755
--- a/tools/android/roll/android_deps/fetch_all.py
+++ b/third_party/android_deps/fetch_all.py
@@ -3,7 +3,6 @@
 # Copyright 2018 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-
 """A script used to manage Google Maven dependencies for Chromium.
 
 This script creates a temporary build directory, where it will, for each
@@ -43,9 +42,8 @@
 import subprocess
 import zipfile
 
-# Assume this script is stored under tools/android/roll/android_deps/
-_CHROMIUM_SRC = os.path.abspath(
-    os.path.join(__file__, '..', '..', '..', '..', '..'))
+# Assume this script is stored under third_party/android_deps/
+_CHROMIUM_SRC = os.path.abspath(os.path.join(__file__, '..', '..', '..'))
 
 # Location of the android_deps directory from a root checkout.
 _ANDROID_DEPS_SUBDIR = 'third_party/android_deps'
@@ -53,6 +51,9 @@
 # Path to BUILD.gn file under android_deps/
 _ANDROID_DEPS_BUILD_GN = _ANDROID_DEPS_SUBDIR + '/BUILD.gn'
 
+# Path to build.gradle file under android_deps/
+_ANDROID_DEPS_BUILD_GRADLE = _ANDROID_DEPS_SUBDIR + '/build.gradle'
+
 # Path to custom licenses under android_deps/
 _ANDROID_DEPS_LICENSE_SUBDIR = _ANDROID_DEPS_SUBDIR + '/licenses'
 
@@ -64,18 +65,19 @@
 _ANDROID_DEPS_LIBS_SUBDIR = _ANDROID_DEPS_SUBDIR + '/libs'
 
 # Location of the buildSrc directory used implement our gradle task.
-_GRADLE_BUILDSRC_PATH = 'tools/android/roll/android_deps/buildSrc'
+_GRADLE_BUILDSRC_PATH = _ANDROID_DEPS_SUBDIR + '/buildSrc'
 
 # The list of git-controlled files that are checked or updated by this tool.
 _UPDATED_GIT_FILES = [
-  'DEPS',
-  _ANDROID_DEPS_BUILD_GN,
-  _ANDROID_DEPS_ADDITIONAL_README_PATHS,
+    'DEPS',
+    _ANDROID_DEPS_BUILD_GN,
+    _ANDROID_DEPS_ADDITIONAL_README_PATHS,
 ]
 
 # If this file exists in an aar file then it is appended to LICENSE
 _THIRD_PARTY_LICENSE_FILENAME = 'third_party_licenses.txt'
 
+
 @contextlib.contextmanager
 def BuildDir(dirname=None):
   """Helper function used to manage a build directory.
@@ -230,8 +232,8 @@
 # - path: Path to cipd.yaml file.
 # - name: cipd package name.
 # - tag: cipd tag.
-CipdPackageInfo = collections.namedtuple(
-    'CipdPackageInfo', ['path', 'name', 'tag'])
+CipdPackageInfo = collections.namedtuple('CipdPackageInfo',
+                                         ['path', 'name', 'tag'])
 
 # Regular expressions used to extract useful info from cipd.yaml files
 # generated by Gradle. See BuildConfigGenerator.groovy:makeCipdYaml()
@@ -308,39 +310,42 @@
     A string holding a shell command to upload the package through cipd.
   """
   pkg_path, pkg_name, pkg_tag = cipd_pkg_info
-  return ('(cd "{0}"; '
-          # Need to skip create step if an instance already exists with the
-          # same package name and version tag (thus the use of ||).
-          'cipd describe "{1}" -version "{2}" || '
-          'cipd create --pkg-def cipd.yaml -tag "{2}")').format(
-              pkg_path, pkg_name, pkg_tag)
+  return (
+      '(cd "{0}"; '
+      # Need to skip create step if an instance already exists with the
+      # same package name and version tag (thus the use of ||).
+      'cipd describe "{1}" -version "{2}" || '
+      'cipd create --pkg-def cipd.yaml -tag "{2}")').format(
+          pkg_path, pkg_name, pkg_tag)
 
 
 def main():
   parser = argparse.ArgumentParser(
-      description=__doc__,
-      formatter_class=argparse.RawDescriptionHelpFormatter)
-  parser.add_argument('--build-dir',
-      help='Path to build directory (default is temporary directory).')
-  parser.add_argument('--chromium-dir',
-      help='Path to Chromium source tree (auto-detect by default).')
-  parser.add_argument('--gradle-wrapper',
-      help='Path to custom gradle wrapper (auto-detect by default).')
+      description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
   parser.add_argument(
-      '--build-gradle',
-      help='Path to build.gradle relative to src/.',
-      default='tools/android/roll/android_deps/build.gradle')
+      '--build-dir',
+      help='Path to build directory (default is temporary directory).')
+  parser.add_argument(
+      '--chromium-dir',
+      help='Path to Chromium source tree (auto-detect by default).')
+  parser.add_argument(
+      '--gradle-wrapper',
+      help='Path to custom gradle wrapper (auto-detect by default).')
   parser.add_argument(
       '--git-dir', help='Path to git subdir from chromium-dir.', default='.')
   parser.add_argument(
       '--ignore-licenses',
       help='Ignores licenses for these deps.',
       action='store_true')
-  parser.add_argument('--update-all', action='store_true',
+  parser.add_argument(
+      '--update-all',
+      action='store_true',
       help='Update current checkout in case of build.gradle changes.'
       'This will also print a list of commands to upload new and updated '
       'packages through cipd, if needed.')
-  parser.add_argument('--reset-workspace', action='store_true',
+  parser.add_argument(
+      '--reset-workspace',
+      action='store_true',
       help='Reset your Chromium workspace to its HEAD state, but preserves '
       'build.gradle changes. Use this to undo previous --update-all changes.')
   parser.add_argument(
@@ -350,7 +355,7 @@
   # Determine Chromium source tree.
   chromium_src = args.chromium_dir
   if not chromium_src:
-    # Assume this script is stored under tools/android/roll/android_deps/
+    # Assume this script is stored under third_party/android_deps/
     chromium_src = _CHROMIUM_SRC
 
   chromium_src = os.path.abspath(chromium_src)
@@ -362,13 +367,15 @@
   if not os.path.isdir(abs_git_dir):
     raise Exception('Not a directory: ' + abs_git_dir)
 
+  build_gradle_path = os.path.join(args.git_dir, _ANDROID_DEPS_BUILD_GRADLE)
+  build_gradle_abs_path = os.path.join(abs_git_dir, _ANDROID_DEPS_BUILD_GRADLE)
   # The list of files and dirs that are copied to the build directory by this
   # script. Should not include _UPDATED_GIT_FILES.
   copied_paths = {
-      args.build_gradle:
-          args.build_gradle,
+      build_gradle_path:
+          build_gradle_path,
       _GRADLE_BUILDSRC_PATH:
-          os.path.join(os.path.dirname(args.build_gradle), "buildSrc"),
+          os.path.join(args.git_dir, _ANDROID_DEPS_SUBDIR, "buildSrc"),
   }
 
   if not args.ignore_licenses:
@@ -387,15 +394,14 @@
       RunCommand(['rm', '-rf', cipd_dir])
 
     print('# Saving build.gradle content')
-    build_gradle_path = os.path.join(chromium_src, args.build_gradle)
-    build_gradle = ReadFile(build_gradle_path)
+    build_gradle = ReadFile(build_gradle_abs_path)
 
     print('# Resetting and re-syncing workspace. (may take a while).')
     RunCommand(['gclient', 'sync', '--reset', '--nohooks', '-r', 'src@HEAD'],
                print_stdout=args.debug)
 
     print('# Restoring build.gradle.')
-    WriteFile(build_gradle_path, build_gradle)
+    WriteFile(build_gradle_abs_path, build_gradle)
     return
 
   missing_files = []
@@ -410,7 +416,7 @@
 
   # Path to the gradlew script used to run build.gradle.
   gradle_wrapper_path = args.gradle_wrapper or os.path.join(
-        chromium_src, 'third_party', 'gradle_wrapper', 'gradlew')
+      chromium_src, 'third_party', 'gradle_wrapper', 'gradlew')
 
   # Path to the aar.py script used to generate .info files.
   aar_py = os.path.join(chromium_src, 'build', 'android', 'gyp', 'aar.py')
@@ -435,7 +441,7 @@
     gradle_cmd = [
         gradle_wrapper_path,
         '-b',
-        os.path.join(build_dir, args.build_gradle),
+        os.path.join(build_dir, build_gradle_path),
         'setupRepository',
         '--stacktrace',
     ]
@@ -470,7 +476,6 @@
             with open(license_path, 'a') as f:
               f.write(z.read(_THIRD_PARTY_LICENSE_FILENAME))
 
-
     print('# Compare CIPD packages.')
     existing_packages = ParseDeps(abs_git_dir, _ANDROID_DEPS_LIBS_SUBDIR)
     build_packages = ParseDeps(
@@ -487,7 +492,7 @@
         build_info = build_packages[pkg]
         if existing_info.tag != build_info.tag:
           logging.info('U %s (%s -> %s)', pkg, existing_info.tag,
-                          build_info.tag)
+                       build_info.tag)
           updated_packages.append(pkg)
         else:
           logging.info('= %s', pkg)  # Unchanged.
@@ -501,11 +506,12 @@
     if cipd_packages_to_upload:
       # TODO(wnwen): Check CIPD to make sure that no other package with the
       #              same tag exists, print error otherwise.
-      cipd_commands = [GenerateCipdUploadCommand(build_packages[pkg])
-        for pkg in cipd_packages_to_upload]
+      cipd_commands = [
+          GenerateCipdUploadCommand(build_packages[pkg])
+          for pkg in cipd_packages_to_upload
+      ]
       # Print them to the log for debugging.
-      logging.info('CIPD update commands\n%s\n',
-                   '\n'.join(cipd_commands))
+      logging.info('CIPD update commands\n%s\n', '\n'.join(cipd_commands))
 
     if not args.update_all:
       if not (deleted_packages or new_packages or updated_packages):
diff --git a/third_party/blink/README.md b/third_party/blink/README.md
index 6c0fcaa9..81b2c9a 100644
--- a/third_party/blink/README.md
+++ b/third_party/blink/README.md
@@ -7,9 +7,10 @@
 
 ## Directory structure
 
-- [`renderer/`](renderer/README.md): code that runs in the renderer process
-  (most of Blink).
 - [`common/`](common/README.md): code that can run in the browser process
   or renderer process.
 - [`public/`](public/README.md): the Blink Public API, used primarily by
   the [content module](/content/README.md).
+- [`renderer/`](renderer/README.md): code that runs in the renderer process
+  (most of Blink).
+- [`web_tests/`](web_tests/README.md): integration tests called "web tests".
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index b003d6e..24610008 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -48,7 +48,6 @@
     "indexeddb/indexeddb_key_range.cc",
     "indexeddb/indexeddb_metadata.cc",
     "input/web_gesture_event.cc",
-    "input/web_keyboard_event.cc",
     "input/web_mouse_event.cc",
     "input/web_mouse_wheel_event.cc",
     "input/web_pointer_event.cc",
diff --git a/third_party/blink/common/input/web_gesture_event.cc b/third_party/blink/common/input/web_gesture_event.cc
index 85a0dc6..512cd96 100644
--- a/third_party/blink/common/input/web_gesture_event.cc
+++ b/third_party/blink/common/input/web_gesture_event.cc
@@ -6,10 +6,6 @@
 
 namespace blink {
 
-std::unique_ptr<WebInputEvent> WebGestureEvent::Clone() const {
-  return std::make_unique<WebGestureEvent>(*this);
-}
-
 float WebGestureEvent::DeltaXInRootFrame() const {
   if (type_ == WebInputEvent::kGestureScrollBegin)
     return data.scroll_begin.delta_x_hint / frame_scale_;
diff --git a/third_party/blink/common/input/web_keyboard_event.cc b/third_party/blink/common/input/web_keyboard_event.cc
deleted file mode 100644
index a75be6d..0000000
--- a/third_party/blink/common/input/web_keyboard_event.cc
+++ /dev/null
@@ -1,13 +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 "third_party/blink/public/common/input/web_keyboard_event.h"
-
-namespace blink {
-
-std::unique_ptr<WebInputEvent> WebKeyboardEvent::Clone() const {
-  return std::make_unique<WebKeyboardEvent>(*this);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/input/web_mouse_event.cc b/third_party/blink/common/input/web_mouse_event.cc
index 5057d07b..1942ad5 100644
--- a/third_party/blink/common/input/web_mouse_event.cc
+++ b/third_party/blink/common/input/web_mouse_event.cc
@@ -15,7 +15,7 @@
                              int modifiers,
                              base::TimeTicks time_stamp,
                              PointerId id_param)
-    : WebInputEvent(type, modifiers, time_stamp),
+    : WebInputEvent(sizeof(WebMouseEvent), type, modifiers, time_stamp),
       WebPointerProperties(id_param,
                            WebPointerProperties::PointerType::kMouse,
                            button_param),
@@ -34,10 +34,6 @@
          frame_translate_;
 }
 
-std::unique_ptr<WebInputEvent> WebMouseEvent::Clone() const {
-  return std::make_unique<WebMouseEvent>(*this);
-}
-
 WebMouseEvent WebMouseEvent::FlattenTransform() const {
   WebMouseEvent result = *this;
   result.FlattenTransformSelf();
diff --git a/third_party/blink/common/input/web_mouse_wheel_event.cc b/third_party/blink/common/input/web_mouse_wheel_event.cc
index eea98f9a..7de30cb 100644
--- a/third_party/blink/common/input/web_mouse_wheel_event.cc
+++ b/third_party/blink/common/input/web_mouse_wheel_event.cc
@@ -6,10 +6,6 @@
 
 namespace blink {
 
-std::unique_ptr<WebInputEvent> WebMouseWheelEvent::Clone() const {
-  return std::make_unique<WebMouseWheelEvent>(*this);
-}
-
 float WebMouseWheelEvent::DeltaXInRootFrame() const {
   return delta_x / frame_scale_;
 }
diff --git a/third_party/blink/common/input/web_pointer_event.cc b/third_party/blink/common/input/web_pointer_event.cc
index aa09d60..3cc2213 100644
--- a/third_party/blink/common/input/web_pointer_event.cc
+++ b/third_party/blink/common/input/web_pointer_event.cc
@@ -30,7 +30,8 @@
 
 WebPointerEvent::WebPointerEvent(const WebTouchEvent& touch_event,
                                  const WebTouchPoint& touch_point)
-    : WebInputEvent(PointerEventTypeForTouchPointState(touch_point.state),
+    : WebInputEvent(sizeof(WebPointerEvent),
+                    PointerEventTypeForTouchPointState(touch_point.state),
                     touch_event.GetModifiers(),
                     touch_event.TimeStamp()),
 
@@ -57,7 +58,10 @@
 
 WebPointerEvent::WebPointerEvent(WebInputEvent::Type type,
                                  const WebMouseEvent& mouse_event)
-    : WebInputEvent(type, mouse_event.GetModifiers(), mouse_event.TimeStamp()),
+    : WebInputEvent(sizeof(WebPointerEvent),
+                    type,
+                    mouse_event.GetModifiers(),
+                    mouse_event.TimeStamp()),
       WebPointerProperties(mouse_event),
       hovering(true),
       width(std::numeric_limits<float>::quiet_NaN()),
@@ -68,10 +72,6 @@
   SetFrameTranslate(mouse_event.FrameTranslate());
 }
 
-std::unique_ptr<WebInputEvent> WebPointerEvent::Clone() const {
-  return std::make_unique<WebPointerEvent>(*this);
-}
-
 WebPointerEvent WebPointerEvent::CreatePointerCausesUaActionEvent(
     WebPointerProperties::PointerType type,
     base::TimeTicks time_stamp) {
diff --git a/third_party/blink/common/input/web_touch_event.cc b/third_party/blink/common/input/web_touch_event.cc
index 20a55c2..ed49046 100644
--- a/third_party/blink/common/input/web_touch_event.cc
+++ b/third_party/blink/common/input/web_touch_event.cc
@@ -6,10 +6,6 @@
 
 namespace blink {
 
-std::unique_ptr<WebInputEvent> WebTouchEvent::Clone() const {
-  return std::make_unique<WebTouchEvent>(*this);
-}
-
 WebTouchEvent WebTouchEvent::FlattenTransform() const {
   WebTouchEvent transformed_event = *this;
   for (unsigned i = 0; i < touches_length; ++i) {
diff --git a/third_party/blink/public/common/input/web_gesture_event.h b/third_party/blink/public/common/input/web_gesture_event.h
index 947c1b6..58195555 100644
--- a/third_party/blink/public/common/input/web_gesture_event.h
+++ b/third_party/blink/public/common/input/web_gesture_event.h
@@ -26,7 +26,7 @@
     kMaxValue = kMomentum,
   };
 
-  bool is_source_touch_event_set_non_blocking = false;
+  bool is_source_touch_event_set_non_blocking;
 
   // The pointer type for the first touch point in the gesture.
   WebPointerProperties::PointerType primary_pointer_type =
@@ -38,7 +38,7 @@
   // not released through a touch event (e.g. timer-released gesture events or
   // gesture events with source_device != WebGestureDevice::kTouchscreen), the
   // field contains 0. See crbug.com/618738.
-  uint32_t unique_touch_event_id = 0;
+  uint32_t unique_touch_event_id;
 
   union {
     // Tap information must be set for GestureTap, GestureTapUnconfirmed,
@@ -180,24 +180,23 @@
   // Screen coordinate
   gfx::PointF position_in_screen_;
 
-  WebGestureDevice source_device_ = WebGestureDevice::kUninitialized;
+  WebGestureDevice source_device_;
 
  public:
   WebGestureEvent(Type type,
                   int modifiers,
                   base::TimeTicks time_stamp,
                   WebGestureDevice device = WebGestureDevice::kUninitialized)
-      : WebInputEvent(type, modifiers, time_stamp), source_device_(device) {
-    memset(&data, 0, sizeof(data));
-  }
+      : WebInputEvent(sizeof(WebGestureEvent), type, modifiers, time_stamp),
+        source_device_(device) {}
 
-  WebGestureEvent() { memset(&data, 0, sizeof(data)); }
+  WebGestureEvent()
+      : WebInputEvent(sizeof(WebGestureEvent)),
+        source_device_(WebGestureDevice::kUninitialized) {}
 
   const gfx::PointF& PositionInWidget() const { return position_in_widget_; }
   const gfx::PointF& PositionInScreen() const { return position_in_screen_; }
 
-  std::unique_ptr<WebInputEvent> Clone() const override;
-
   void SetPositionInWidget(const gfx::PointF& point) {
     position_in_widget_ = point;
   }
diff --git a/third_party/blink/public/common/input/web_input_event.h b/third_party/blink/public/common/input/web_input_event.h
index 5d30b5e..c137231 100644
--- a/third_party/blink/public/common/input/web_input_event.h
+++ b/third_party/blink/public/common/input/web_input_event.h
@@ -42,7 +42,7 @@
 
 // WebInputEvent --------------------------------------------------------------
 
-class BLINK_COMMON_EXPORT WebInputEvent {
+class WebInputEvent {
  public:
   // When we use an input method (or an input method editor), we receive
   // two events for a keypress. The former event is a keydown, which
@@ -426,30 +426,61 @@
   base::TimeTicks TimeStamp() const { return time_stamp_; }
   void SetTimeStamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; }
 
+  unsigned size() const { return size_; }
+
   void SetTargetFrameMovedRecently() {
     modifiers_ |= kTargetFrameMovedRecently;
   }
 
-  virtual ~WebInputEvent() = default;
-
-  virtual std::unique_ptr<WebInputEvent> Clone() const = 0;
-
  protected:
   // The root frame scale.
-  float frame_scale_ = 1;
+  float frame_scale_;
 
   // The root frame translation (applied post scale).
   gfx::Vector2dF frame_translate_;
 
-  WebInputEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : time_stamp_(time_stamp), type_(type), modifiers_(modifiers) {}
+  WebInputEvent(unsigned size,
+                Type type,
+                int modifiers,
+                base::TimeTicks time_stamp) {
+    // TODO(dtapuska): Remove this memset when we remove the chrome IPC of this
+    // struct.
+    memset(this, 0, size);
+    time_stamp_ = time_stamp;
+    size_ = size;
+    type_ = type;
+    modifiers_ = modifiers;
+#if DCHECK_IS_ON()
+    // If dcheck is on force failures if frame scale is not initialized
+    // correctly by causing DIV0.
+    frame_scale_ = 0;
+#else
+    frame_scale_ = 1;
+#endif
+  }
 
-  WebInputEvent() { time_stamp_ = base::TimeTicks(); }
+  explicit WebInputEvent(unsigned size_param) {
+    // TODO(dtapuska): Remove this memset when we remove the chrome IPC of this
+    // struct.
+    memset(this, 0, size_param);
+    time_stamp_ = base::TimeTicks();
+    size_ = size_param;
+    type_ = kUndefined;
+#if DCHECK_IS_ON()
+    // If dcheck is on force failures if frame scale is not initialized
+    // correctly by causing DIV0.
+    frame_scale_ = 0;
+#else
+    frame_scale_ = 1;
+#endif
+  }
 
   // Event time since platform start with microsecond resolution.
   base::TimeTicks time_stamp_;
-  Type type_ = kUndefined;
-  int modifiers_ = kNoModifiers;
+  // The size of this structure, for serialization.
+  unsigned size_;
+  Type type_;
+  int modifiers_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/input/web_keyboard_event.h b/third_party/blink/public/common/input/web_keyboard_event.h
index 5f38e9e..18cfb20d 100644
--- a/third_party/blink/public/common/input/web_keyboard_event.h
+++ b/third_party/blink/public/common/input/web_keyboard_event.h
@@ -12,7 +12,7 @@
 
 // WebKeyboardEvent -----------------------------------------------------------
 
-class BLINK_COMMON_EXPORT WebKeyboardEvent : public WebInputEvent {
+class WebKeyboardEvent : public WebInputEvent {
  public:
   // Caps on string lengths so we can make them static arrays and keep
   // them PODs.
@@ -26,32 +26,32 @@
   // what is returned by the Windows API. For example, it should
   // store VK_SHIFT instead of VK_RSHIFT. The location information
   // should be stored in |modifiers|.
-  int windows_key_code = 0;
+  int windows_key_code;
 
   // The actual key code genenerated by the platform. The DOM spec runs
   // on Windows-equivalent codes (thus |windows_key_code| above) but it
   // doesn't hurt to have this one around.
-  int native_key_code = 0;
+  int native_key_code;
 
   // The DOM code enum of the key pressed as passed by the embedder. DOM code
   // enums are defined in ui/events/keycodes/dom/keycode_converter_data.inc.
-  int dom_code = 0;
+  int dom_code;
 
   // The DOM key enum of the key pressed as passed by the embedder. DOM
   // key enums are defined in ui/events/keycodes/dom/dom_key_data.inc.
-  int dom_key = 0;
+  int dom_key;
 
   // This identifies whether this event was tagged by the system as being a
   // "system key" event (see
   // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-syskeydown for
   // details). Other platforms don't have this concept, but it's just
   // easier to leave it always false than ifdef.
-  bool is_system_key = false;
+  bool is_system_key;
 
   // Whether the event forms part of a browser-handled keyboard shortcut.
   // This can be used to conditionally suppress Char events after a
   // shortcut-triggering RawKeyDown goes unhandled.
-  bool is_browser_shortcut = false;
+  bool is_browser_shortcut;
 
   // |text| is the text generated by this keystroke.  |unmodified_text| is
   // |text|, but unmodified by an concurrently-held modifiers (except
@@ -59,15 +59,13 @@
   // Windows guarantee one character per event.  The Mac does not, but in
   // reality that's all it ever gives.  We're generous, and cap it a bit
   // longer.
-  base::char16 text[kTextLengthCap] = {};
-  base::char16 unmodified_text[kTextLengthCap] = {};
+  base::char16 text[kTextLengthCap];
+  base::char16 unmodified_text[kTextLengthCap];
 
   WebKeyboardEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebInputEvent(type, modifiers, time_stamp) {}
+      : WebInputEvent(sizeof(WebKeyboardEvent), type, modifiers, time_stamp) {}
 
-  WebKeyboardEvent() = default;
-
-  std::unique_ptr<WebInputEvent> Clone() const override;
+  WebKeyboardEvent() : WebInputEvent(sizeof(WebKeyboardEvent)) {}
 
   // Please refer to bug http://b/issue?id=961192, which talks about Webkit
   // keyboard event handling changes. It also mentions the list of keys
diff --git a/third_party/blink/public/common/input/web_mouse_event.h b/third_party/blink/public/common/input/web_mouse_event.h
index 957e83c2..25da4f1 100644
--- a/third_party/blink/public/common/input/web_mouse_event.h
+++ b/third_party/blink/public/common/input/web_mouse_event.h
@@ -20,10 +20,10 @@
  public:
   static constexpr PointerId kMousePointerId = std::numeric_limits<int>::max();
 
-  int click_count = {};
+  int click_count;
 
   // Only used for contextmenu events.
-  WebMenuSourceType menu_source_type = kMenuSourceNone;
+  WebMenuSourceType menu_source_type;
 
   WebMouseEvent(Type type_param,
                 gfx::PointF position,
@@ -34,7 +34,10 @@
                 base::TimeTicks time_stamp_param,
                 WebMenuSourceType menu_source_type_param = kMenuSourceNone,
                 PointerId id_param = kMousePointerId)
-      : WebInputEvent(type_param, modifiers_param, time_stamp_param),
+      : WebInputEvent(sizeof(WebMouseEvent),
+                      type_param,
+                      modifiers_param,
+                      time_stamp_param),
         WebPointerProperties(id_param,
                              PointerType::kMouse,
                              button_param,
@@ -50,10 +53,13 @@
                 int modifiers_param,
                 base::TimeTicks time_stamp_param,
                 PointerId id_param = kMousePointerId)
-      : WebInputEvent(type_param, modifiers_param, time_stamp_param),
-        WebPointerProperties(id_param) {}
+      : WebMouseEvent(sizeof(WebMouseEvent),
+                      type_param,
+                      modifiers_param,
+                      time_stamp_param,
+                      id_param) {}
 
-  WebMouseEvent() : WebMouseEvent(kMousePointerId) {}
+  WebMouseEvent() : WebMouseEvent(sizeof(WebMouseEvent), kMousePointerId) {}
 
   bool FromTouch() const {
     return (GetModifiers() & kIsCompatibilityEventForTouch) != 0;
@@ -67,8 +73,6 @@
                 base::TimeTicks time_stamp_param,
                 PointerId id_param = kMousePointerId);
 
-  std::unique_ptr<WebInputEvent> Clone() const override;
-
   gfx::PointF PositionInRootFrame() const;
 
   // Sets any scaled values to be their computed values and sets |frame_scale_|
@@ -76,7 +80,16 @@
   WebMouseEvent FlattenTransform() const;
 
  protected:
-  WebMouseEvent(PointerId id_param) : WebPointerProperties(id_param) {}
+  WebMouseEvent(unsigned size_param, PointerId id_param)
+      : WebInputEvent(size_param), WebPointerProperties(id_param) {}
+
+  WebMouseEvent(unsigned size_param,
+                Type type,
+                int modifiers,
+                base::TimeTicks time_stamp,
+                PointerId id_param)
+      : WebInputEvent(size_param, type, modifiers, time_stamp),
+        WebPointerProperties(id_param) {}
 
   void FlattenTransformSelf();
 
diff --git a/third_party/blink/public/common/input/web_mouse_wheel_event.h b/third_party/blink/public/common/input/web_mouse_wheel_event.h
index 79697fe..605740b8 100644
--- a/third_party/blink/public/common/input/web_mouse_wheel_event.h
+++ b/third_party/blink/public/common/input/web_mouse_wheel_event.h
@@ -52,25 +52,25 @@
     kScrollVertical
   };
 
-  float delta_x = 0.0f;
-  float delta_y = 0.0f;
-  float wheel_ticks_x = 0.0f;
-  float wheel_ticks_y = 0.0f;
+  float delta_x;
+  float delta_y;
+  float wheel_ticks_x;
+  float wheel_ticks_y;
 
-  float acceleration_ratio_x = 1.0f;
-  float acceleration_ratio_y = 1.0f;
+  float acceleration_ratio_x;
+  float acceleration_ratio_y;
 
-  Phase phase = kPhaseNone;
-  Phase momentum_phase = kPhaseNone;
+  Phase phase;
+  Phase momentum_phase;
 
-  RailsMode rails_mode = kRailsModeFree;
+  RailsMode rails_mode;
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type = kBlocking;
+  DispatchType dispatch_type;
 
   // The expected result of this wheel event (if not canceled).
-  EventAction event_action = EventAction::kPageZoom;
+  EventAction event_action;
 
   // True when phase information is added in mouse_wheel_phase_handler based
   // on its timer.
@@ -80,13 +80,39 @@
   // kScrollByPrecisePixel, kScrollByPixel, and kScrollByPage, as they are
   // the only values expected after converting an OS event to a
   // WebMouseWheelEvent.
-  ui::input_types::ScrollGranularity delta_units =
-      ui::input_types::ScrollGranularity::kScrollByPixel;
+  ui::input_types::ScrollGranularity delta_units;
 
   WebMouseWheelEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebMouseEvent(type, modifiers, time_stamp, kMousePointerId) {}
+      : WebMouseEvent(sizeof(WebMouseWheelEvent),
+                      type,
+                      modifiers,
+                      time_stamp,
+                      kMousePointerId),
+        delta_x(0.0f),
+        delta_y(0.0f),
+        wheel_ticks_x(0.0f),
+        wheel_ticks_y(0.0f),
+        acceleration_ratio_x(1.0f),
+        acceleration_ratio_y(1.0f),
+        phase(kPhaseNone),
+        momentum_phase(kPhaseNone),
+        rails_mode(kRailsModeFree),
+        dispatch_type(kBlocking),
+        delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
 
-  WebMouseWheelEvent() : WebMouseEvent(kMousePointerId) {}
+  WebMouseWheelEvent()
+      : WebMouseEvent(sizeof(WebMouseWheelEvent), kMousePointerId),
+        delta_x(0.0f),
+        delta_y(0.0f),
+        wheel_ticks_x(0.0f),
+        wheel_ticks_y(0.0f),
+        acceleration_ratio_x(1.0f),
+        acceleration_ratio_y(1.0f),
+        phase(kPhaseNone),
+        momentum_phase(kPhaseNone),
+        rails_mode(kRailsModeFree),
+        dispatch_type(kBlocking),
+        delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
 
   float DeltaXInRootFrame() const;
   float DeltaYInRootFrame() const;
@@ -96,8 +122,6 @@
   WebMouseWheelEvent FlattenTransform() const;
 
   bool IsCancelable() const { return dispatch_type == kBlocking; }
-
-  std::unique_ptr<WebInputEvent> Clone() const override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/input/web_pointer_event.h b/third_party/blink/public/common/input/web_pointer_event.h
index efb5847e..cdf6b99 100644
--- a/third_party/blink/public/common/input/web_pointer_event.h
+++ b/third_party/blink/public/common/input/web_pointer_event.h
@@ -21,12 +21,14 @@
 class BLINK_COMMON_EXPORT WebPointerEvent : public WebInputEvent,
                                             public WebPointerProperties {
  public:
-  WebPointerEvent() : WebPointerProperties(0) {}
+  WebPointerEvent()
+      : WebInputEvent(sizeof(WebPointerEvent)), WebPointerProperties(0) {}
   WebPointerEvent(WebInputEvent::Type type_param,
                   WebPointerProperties web_pointer_properties_param,
                   float width_param,
                   float height_param)
-      : WebPointerProperties(web_pointer_properties_param),
+      : WebInputEvent(sizeof(WebPointerEvent)),
+        WebPointerProperties(web_pointer_properties_param),
         width(width_param),
         height(height_param) {
     SetType(type_param);
@@ -34,46 +36,44 @@
   WebPointerEvent(const WebTouchEvent&, const WebTouchPoint&);
   WebPointerEvent(WebInputEvent::Type, const WebMouseEvent&);
 
-  std::unique_ptr<WebInputEvent> Clone() const override;
-
   static WebPointerEvent CreatePointerCausesUaActionEvent(
       WebPointerProperties::PointerType,
       base::TimeTicks time_stamp);
 
   // ------------ Touch Point Specific ------------
 
-  float rotation_angle = 0.0f;
+  float rotation_angle;
 
   // ------------ Touch Event Specific ------------
 
   // A unique identifier for the touch event. Valid ids start at one and
   // increase monotonically. Zero means an unknown id.
-  uint32_t unique_touch_event_id = 0;
+  uint32_t unique_touch_event_id;
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type = kBlocking;
+  DispatchType dispatch_type;
 
   // For a single touch, this is true after the touch-point has moved beyond
   // the platform slop region. For a multitouch, this is true after any
   // touch-point has moved (by whatever amount).
-  bool moved_beyond_slop_region = false;
+  bool moved_beyond_slop_region;
 
   // Whether this touch event is a touchstart or a first touchmove event per
   // scroll.
-  bool touch_start_or_first_touch_move = false;
+  bool touch_start_or_first_touch_move;
 
   // ------------ Common fields across pointer types ------------
 
   // True if this pointer was hovering and false otherwise. False value entails
   // the event was processed as part of gesture detection and it may cause
   // scrolling.
-  bool hovering = false;
+  bool hovering;
 
   // TODO(crbug.com/736014): We need a clarified definition of the scale and
   // the coordinate space on these attributes.
-  float width = 0.0f;
-  float height = 0.0f;
+  float width;
+  float height;
 
   bool IsCancelable() const { return dispatch_type == kBlocking; }
   bool HasWidth() const { return !std::isnan(width); }
diff --git a/third_party/blink/public/common/input/web_pointer_properties.h b/third_party/blink/public/common/input/web_pointer_properties.h
index c642fab..d122090f 100644
--- a/third_party/blink/public/common/input/web_pointer_properties.h
+++ b/third_party/blink/public/common/input/web_pointer_properties.h
@@ -60,10 +60,16 @@
       int movement_x = 0,
       int movement_y = 0)
       : id(id_param),
+        force(std::numeric_limits<float>::quiet_NaN()),
+        tilt_x(0),
+        tilt_y(0),
+        tangential_pressure(0.0f),
+        twist(0),
         button(button_param),
         pointer_type(pointer_type_param),
         movement_x(movement_x),
         movement_y(movement_y),
+        is_raw_movement_event(false),
         position_in_widget_(position_in_widget),
         position_in_screen_(position_in_screen) {}
 
@@ -90,23 +96,23 @@
 
   // The valid range is [0,1], with NaN meaning pressure is not supported by
   // the input device.
-  float force = std::numeric_limits<float>::quiet_NaN();
+  float force;
 
   // Tilt of a pen stylus from surface normal as plane angles in degrees,
   // Values lie in [-90,90]. A positive tiltX is to the right and a positive
   // tiltY is towards the user.
-  int tilt_x = 0;
-  int tilt_y = 0;
+  int tilt_x;
+  int tilt_y;
 
   // The normalized tangential pressure (or barrel pressure), typically set by
   // an additional control of the stylus, which has a range of [-1,1], where 0
   // is the neutral position of the control. Always 0 if the device does not
   // support it.
-  float tangential_pressure = 0.0f;
+  float tangential_pressure;
 
   // The clockwise rotation of a pen stylus around its own major axis, in
   // degrees in the range [0,359]. Always 0 if the device does not support it.
-  int twist = 0;
+  int twist;
 
   // - For pointerup/down events, the button of pointing device that triggered
   // the event.
@@ -122,7 +128,7 @@
 
   // True if this event has raw movement value from OS.
   // TODO(crbug.com/982379): Figure out how to avoid using this boolean.
-  bool is_raw_movement_event = false;
+  bool is_raw_movement_event;
 
  protected:
   // Widget coordinate, which is relative to the bound of current RenderWidget
diff --git a/third_party/blink/public/common/input/web_touch_event.h b/third_party/blink/public/common/input/web_touch_event.h
index 9a59b3f..795976c 100644
--- a/third_party/blink/public/common/input/web_touch_event.h
+++ b/third_party/blink/public/common/input/web_touch_event.h
@@ -19,37 +19,37 @@
   // Ash/Aura.
   enum { kTouchesLengthCap = 16 };
 
-  unsigned touches_length = 0;
+  unsigned touches_length;
   // List of all touches, regardless of state.
-  WebTouchPoint touches[kTouchesLengthCap] = {};
+  WebTouchPoint touches[kTouchesLengthCap];
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type = kBlocking;
+  DispatchType dispatch_type;
 
   // For a single touch, this is true after the touch-point has moved beyond
   // the platform slop region. For a multitouch, this is true after any
   // touch-point has moved (by whatever amount).
-  bool moved_beyond_slop_region = false;
+  bool moved_beyond_slop_region;
 
   // True for events from devices like some pens that support hovering
   // over digitizer and the events are sent while the device was hovering.
-  bool hovering = false;
+  bool hovering;
 
   // Whether this touch event is a touchstart or a first touchmove event per
   // scroll.
-  bool touch_start_or_first_touch_move = false;
+  bool touch_start_or_first_touch_move;
 
   // A unique identifier for the touch event. Valid ids start at one and
   // increase monotonically. Zero means an unknown id.
-  uint32_t unique_touch_event_id = 0;
+  uint32_t unique_touch_event_id;
 
-  WebTouchEvent() = default;
+  WebTouchEvent()
+      : WebInputEvent(sizeof(WebTouchEvent)), dispatch_type(kBlocking) {}
 
   WebTouchEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebInputEvent(type, modifiers, time_stamp) {}
-
-  std::unique_ptr<WebInputEvent> Clone() const override;
+      : WebInputEvent(sizeof(WebTouchEvent), type, modifiers, time_stamp),
+        dispatch_type(kBlocking) {}
 
   // Sets any scaled values to be their computed values and sets |frame_scale_|
   // back to 1 and |frame_translate_| X and Y coordinates back to 0.
diff --git a/third_party/blink/public/common/input/web_touch_point.h b/third_party/blink/public/common/input/web_touch_point.h
index 939142e..de8971f6 100644
--- a/third_party/blink/public/common/input/web_touch_point.h
+++ b/third_party/blink/public/common/input/web_touch_point.h
@@ -38,12 +38,16 @@
 
 // TODO(mustaq): Unify WebTouchPoint & WebMouseEvent into WebPointerEvent.
 // crbug.com/508283
-class BLINK_COMMON_EXPORT WebTouchPoint : public WebPointerProperties {
+class WebTouchPoint : public WebPointerProperties {
  public:
   WebTouchPoint() : WebTouchPoint(WebPointerProperties(0)) {}
 
   WebTouchPoint(WebPointerProperties web_pointer_properties)
-      : WebPointerProperties(web_pointer_properties) {}
+      : WebPointerProperties(web_pointer_properties),
+        state(kStateUndefined),
+        radius_x(0),
+        radius_y(0),
+        rotation_angle(0) {}
 
   enum State {
     kStateUndefined,
@@ -55,11 +59,11 @@
     kStateMax = kStateCancelled
   };
 
-  State state = kStateUndefined;
+  State state;
 
-  float radius_x = 0.0f;
-  float radius_y = 0.0f;
-  float rotation_angle = 0.0f;
+  float radius_x;
+  float radius_y;
+  float rotation_angle;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index ee9a0c5..0558617 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -30,6 +30,7 @@
     "+media/base/video_transformation.h",
     "+mojo/public",
     "+net/cert",
+    "+net/dns/public",
     "+net/http",
     "+services/network/public/cpp/cors/cors_error_status.h",
     "+services/network/public/cpp/cors/preflight_result.h",
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 653c9f2..8690ec1 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -578,7 +578,7 @@
 
   virtual bool IsWebRtcSrtpEncryptedHeadersEnabled() { return false; }
 
-  virtual base::Optional<std::string> WebRtcStunProbeTrialParameter() {
+  virtual base::Optional<WebString> WebRtcStunProbeTrialParameter() {
     return base::nullopt;
   }
 
diff --git a/third_party/blink/public/platform/web_coalesced_input_event.h b/third_party/blink/public/platform/web_coalesced_input_event.h
index 3095d0bb..bcf03594 100644
--- a/third_party/blink/public/platform/web_coalesced_input_event.h
+++ b/third_party/blink/public/platform/web_coalesced_input_event.h
@@ -42,7 +42,12 @@
   WebVector<const WebInputEvent*> GetPredictedEventsPointers() const;
 
  private:
-  using WebScopedInputEvent = std::unique_ptr<WebInputEvent>;
+  struct BLINK_PLATFORM_EXPORT WebInputEventDeleter {
+    void operator()(blink::WebInputEvent*) const;
+  };
+
+  using WebScopedInputEvent =
+      std::unique_ptr<WebInputEvent, WebInputEventDeleter>;
 
   WebScopedInputEvent MakeWebScopedInputEvent(const blink::WebInputEvent&);
 
diff --git a/third_party/blink/public/platform/web_url_error.h b/third_party/blink/public/platform/web_url_error.h
index 43995b5..8ede395 100644
--- a/third_party/blink/public/platform/web_url_error.h
+++ b/third_party/blink/public/platform/web_url_error.h
@@ -33,6 +33,7 @@
 
 #include "base/logging.h"
 #include "base/optional.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "third_party/blink/public/platform/web_url.h"
 
@@ -56,6 +57,7 @@
   // |reason| must not be 0.
   BLINK_PLATFORM_EXPORT WebURLError(int reason,
                                     int extended_reason,
+                                    net::ResolveErrorInfo resolve_error_info,
                                     HasCopyInCache,
                                     IsWebSecurityViolation,
                                     const WebURL&);
@@ -65,6 +67,9 @@
 
   int reason() const { return reason_; }
   int extended_reason() const { return extended_reason_; }
+  const net::ResolveErrorInfo& resolve_error_info() const {
+    return resolve_error_info_;
+  }
   bool has_copy_in_cache() const { return has_copy_in_cache_; }
   bool is_web_security_violation() const { return is_web_security_violation_; }
   const WebURL& url() const { return url_; }
@@ -80,6 +85,9 @@
   // Additional information based on the reason_.
   int extended_reason_ = 0;
 
+  // Detailed host resolution error information.
+  net::ResolveErrorInfo resolve_error_info_;
+
   // A flag showing whether or not we have a (possibly stale) copy of the
   // requested resource in the cache.
   bool has_copy_in_cache_ = false;
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
index a475a44..af5a7b28 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -8,14 +8,36 @@
 specific bindings, such as ECMAScript bindings.
 """
 
-import copy
-
 from .codegen_accumulator import CodeGenAccumulator
 from .codegen_format import format_template
 from .mako_renderer import MakoRenderer
 from .mako_renderer import MakoTemplate
 
 
+def render_code_node(code_node):
+    """
+    Renders |code_node| and turns it into text letting |code_node| apply all
+    necessary changes (side effects).  Returns the resulting text.
+    """
+    assert isinstance(code_node, CodeNode)
+    assert code_node.outer is None
+
+    renderer = code_node.renderer
+    accumulator = code_node.accumulator
+
+    accumulated_size = accumulator.total_size()
+    while True:
+        prev_accumulated_size = accumulated_size
+        renderer.reset()
+        code_node.render(renderer)
+        accumulated_size = accumulator.total_size()
+        if (renderer.is_rendering_complete()
+                and accumulated_size == prev_accumulated_size):
+            break
+
+    return renderer.to_text()
+
+
 class Likeliness(object):
     """
     Represents how much likely a code node will be executed.
@@ -145,10 +167,14 @@
             self._template = None
         else:
             self._template = MakoTemplate(template_text)
-        self._template_vars = {}
+
+        # Template variable bindings
+        self._own_template_vars = None
+        self._base_template_vars = None
+        self._cached_template_vars = None
 
         self._accumulator = None  # CodeGenAccumulator
-        self._accumulate_requests = []
+        self._accumulate_requests = None
 
         self._renderer = None  # MakoRenderer
 
@@ -160,27 +186,32 @@
 
     def __str__(self):
         """
-        Renders this CodeNode object into a Mako template.  This is supposed to
-        be used in a Mako template as ${code_node}.
-        """
-        return self.render()
+        Renders this CodeNode object directly into the renderer's text buffer
+        and always returns the empty string.  This is because it's faster to
+        accumulate the rendering result directly in a single text buffer than
+        making a lot of string pieces and concatenating them.
 
-    def render(self):
+        This function is supposed to be used in a Mako template as ${code_node}.
+        """
+        renderer = self.renderer
+        assert renderer
+
+        self.render(renderer)
+        return ""
+
+    def render(self, renderer):
         """
         Renders this CodeNode object as a text string and also propagates
         updates to related CodeNode objects.  As this method has side-effects
         not only to this object but also other related objects, the resulting
         text may change on each invocation.
         """
-        renderer = self.renderer
-        assert renderer
-
         last_render_state = self._render_state
         self._render_state = CodeNode._RenderState()
         self._is_rendering = True
 
         try:
-            text = self._render(
+            self._render(
                 renderer=renderer, last_render_state=last_render_state)
         finally:
             self._is_rendering = False
@@ -190,9 +221,7 @@
             assert accumulator
             for request in self._accumulate_requests:
                 request(accumulator)
-            self._accumulate_requests = []
-
-        return text
+            self._accumulate_requests = None
 
     def _render(self, renderer, last_render_state):
         """
@@ -201,7 +230,7 @@
 
         Only limited subclasses may override this method.
         """
-        return renderer.render(
+        renderer.render(
             caller=self,
             template=self._template,
             template_vars=self.template_vars)
@@ -250,34 +279,65 @@
             node = node.outer
         return node
 
+    def inclusive_outers(self):
+        """
+        Returns a list of outer nodes including this node in order from this
+        node to the outermost node.
+        """
+        outers = []
+        node = self
+        while node is not None:
+            outers.append(node)
+            node = node.outer
+        return outers
+
     @property
     def template_vars(self):
         """
         Returns the template variable bindings available at this point, i.e.
         bound at this node or outer nodes.
 
-        CAUTION: Do not modify the returned dict.  This method may return the
-        original dict in a CodeNode.
+        CAUTION: This accessor caches the result.  This accessor must not be
+        called during construction of a code node tree.
         """
-        if not self.outer:
-            return self._template_vars
+        if self._cached_template_vars is not None:
+            return self._cached_template_vars
 
-        if not self._template_vars:
-            return self.outer.template_vars
+        outers = self.inclusive_outers()
+        bindings = None
 
-        binds = copy.copy(self.outer.template_vars)
-        for name, value in self._template_vars.iteritems():
-            assert name not in binds, (
-                "Duplicated template variable binding: {}".format(name))
-            binds[name] = value
-        return binds
+        for node in outers:
+            if node.base_template_vars is not None:
+                bindings = dict(node.base_template_vars)
+                break
+        if bindings is None:
+            bindings = {}
+
+        for node in outers:
+            if node.own_template_vars is None:
+                continue
+            for name, value in node.own_template_vars.iteritems():
+                assert name not in bindings, (
+                    "Duplicated template variable binding: {}".format(name))
+                bindings[name] = value
+
+        self._cached_template_vars = bindings
+        return self._cached_template_vars
+
+    @property
+    def own_template_vars(self):
+        """Returns the template variables bound at this code node."""
+        return self._own_template_vars
 
     def add_template_var(self, name, value):
-        assert name not in self._template_vars, (
+        if self._own_template_vars is None:
+            self._own_template_vars = {}
+        assert isinstance(name, str)
+        assert name not in self._own_template_vars, (
             "Duplicated template variable binding: {}".format(name))
         if isinstance(value, CodeNode):
             value.set_outer(self)
-        self._template_vars[name] = value
+        self._own_template_vars[name] = value
 
     def add_template_vars(self, template_vars):
         assert isinstance(template_vars, dict)
@@ -285,6 +345,25 @@
             self.add_template_var(name, value)
 
     @property
+    def base_template_vars(self):
+        """
+        Returns the base template variables if it's set at this code node.
+
+        The base template variables are a set of template variables that of
+        the innermost code node takes effect.  It means that the base template
+        variables are layered and shadowable.
+        """
+        return self._base_template_vars
+
+    def set_base_template_vars(self, template_vars):
+        assert isinstance(template_vars, dict)
+        for name, value in template_vars.iteritems():
+            assert isinstance(name, str)
+            assert not isinstance(value, CodeNode)
+        assert self._base_template_vars is None
+        self._base_template_vars = template_vars
+
+    @property
     def accumulator(self):
         # Always consistently use the accumulator of the root node.
         if self.outer is None:
@@ -302,6 +381,8 @@
         argument of self.accumulator.
         """
         assert callable(request)
+        if self._accumulate_requests is None:
+            self._accumulate_requests = []
         self._accumulate_requests.append(request)
 
     @property
@@ -336,23 +417,58 @@
             symbol_node, set()).add(symbol_scope_chain)
 
 
+class EmptyNode(CodeNode):
+    """Represents the zero-length text and renders nothing."""
+
+    def __init__(self):
+        CodeNode.__init__(self)
+
+    def _render(self, renderer, last_render_state):
+        pass
+
+
 class LiteralNode(CodeNode):
     """
     Represents a literal text, which will be rendered as is without any template
-    magic applied.
+    magic applied.  The given literal text object will be stringified on each
+    rendering.
     """
 
     def __init__(self, literal_text):
-        literal_text_gensym = CodeNode.gensym()
-        template_text = format_template(
-            "${{{literal_text}}}", literal_text=literal_text_gensym)
-        template_vars = {literal_text_gensym: literal_text}
+        CodeNode.__init__(self)
 
-        CodeNode.__init__(
-            self, template_text=template_text, template_vars=template_vars)
+        self._literal_text = literal_text
+
+    def _render(self, renderer, last_render_state):
+        renderer.push_caller(self)
+        try:
+            renderer.render_text(str(self._literal_text))
+        finally:
+            renderer.pop_caller()
 
 
-class TextNode(CodeNode):
+def TextNode(template_text):
+    """
+    Represents a template text node.
+
+    TextNode is designed to be a leaf node of a code node tree.  TextNode
+    represents a template text while LiteralNode represents a literal text.
+    All template magics will be applied to |template_text|.
+
+    This function is pretending to be a CodeNode subclass and instantiates one
+    of text-ish code node subclass depending on the content of |template_text|.
+    """
+    assert isinstance(template_text, str)
+
+    if "$" in template_text or "%" in template_text:
+        return _TextNode(template_text)
+    elif template_text:
+        return LiteralNode(template_text)
+    else:
+        return EmptyNode()
+
+
+class _TextNode(CodeNode):
     """
     Represents a template text node.
 
@@ -425,33 +541,14 @@
         assert isinstance(head, str)
         assert isinstance(tail, str)
 
-        element_nodes_gensym = CodeNode.gensym()
-        element_nodes = []
-        template_text = format_template(
-            """\
-% if {element_nodes}:
-{head}\\
-% endif
-% for node in {element_nodes}:
-${node}\\
-% if not loop.last:
-{separator}\\
-% endif
-% endfor
-% if {element_nodes}:
-{tail}\\
-% endif\
-""",
-            element_nodes=element_nodes_gensym,
-            separator=separator,
-            head=head,
-            tail=tail)
-        template_vars = {element_nodes_gensym: element_nodes}
+        CodeNode.__init__(self)
 
-        CodeNode.__init__(
-            self, template_text=template_text, template_vars=template_vars)
+        self._element_nodes = []
+        self._separator = separator
+        self._head = head
+        self._tail = tail
 
-        self._element_nodes = element_nodes
+        self._will_skip_separator = False
 
         if code_nodes is not None:
             self.extend(code_nodes)
@@ -465,6 +562,26 @@
     def __len__(self):
         return len(self._element_nodes)
 
+    def _render(self, renderer, last_render_state):
+        renderer.push_caller(self)
+        try:
+            if self._element_nodes:
+                renderer.render_text(self._head)
+            self._will_skip_separator = True
+            for node in self._element_nodes:
+                if self._will_skip_separator:
+                    self._will_skip_separator = False
+                else:
+                    renderer.render_text(self._separator)
+                node.render(renderer)
+            if self._element_nodes:
+                renderer.render_text(self._tail)
+        finally:
+            renderer.pop_caller()
+
+    def skip_separator(self):
+        self._will_skip_separator = True
+
     def append(self, node):
         if node is None:
             return
@@ -541,7 +658,7 @@
                 self.remove(node)
             self._to_be_removed = []
 
-        return super(SequenceNode, self)._render(
+        super(SequenceNode, self)._render(
             renderer=renderer, last_render_state=last_render_state)
 
     def schedule_to_remove(self, node):
@@ -575,9 +692,12 @@
             if not self.is_code_symbol_defined(symbol_node):
                 self._insert_symbol_definition(symbol_node, last_render_state)
 
-        return super(SymbolScopeNode, self)._render(
+        super(SymbolScopeNode, self)._render(
             renderer=renderer, last_render_state=last_render_state)
 
+        if self.current_render_state.undefined_code_symbols:
+            renderer.invalidate_rendering_result()
+
     def _insert_symbol_definition(self, symbol_node, last_render_state):
         DIRECT_USES = "u"
         DIRECT_CHILD_SCOPES = "s"
@@ -760,6 +880,14 @@
             self._definition_constructor = definition_constructor
 
     def _render(self, renderer, last_render_state):
+        self._request_symbol_definition(renderer)
+
+        renderer.render_text(self.name)
+
+    def request_symbol_definition(self):
+        self._request_symbol_definition(self.renderer)
+
+    def _request_symbol_definition(self, renderer):
         symbol_scope_chain = tuple(
             filter(lambda node: isinstance(node, SymbolScopeNode),
                    renderer.callers_from_first_to_last))
@@ -775,8 +903,6 @@
                 if scope is self.outer:
                     break
 
-        return self.name
-
     @property
     def name(self):
         return self._name
@@ -809,11 +935,12 @@
         if scope.is_code_symbol_defined(self._symbol_node):
             assert isinstance(self.outer, SequenceNode)
             self.outer.schedule_to_remove(self)
-            return ""
+            self.outer.skip_separator()
+            return
 
         scope.on_code_symbol_defined(self._symbol_node)
 
-        return super(SymbolDefinitionNode, self)._render(
+        super(SymbolDefinitionNode, self)._render(
             renderer=renderer, last_render_state=last_render_state)
 
     @property
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
index ede35d792..802e331 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
@@ -280,7 +280,7 @@
         """
         assert isinstance(final, bool)
 
-        template_format = ("{export}class {name}{final}{base_clause} {{\n"
+        template_format = ("class{export} {name}{final}{base_clause} {{\n"
                            "  {top_section}\n"
                            "  {public_section}\n"
                            "  {protected_section}\n"
@@ -291,7 +291,7 @@
         if export is None:
             export = ""
         else:
-            export = ListNode([_to_maybe_text_node(export)], tail=" ")
+            export = ListNode([_to_maybe_text_node(export)], head=" ")
 
         final = " final" if final else ""
 
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
index d24b3a7..a18f304e 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
@@ -7,11 +7,12 @@
 from .code_node import SymbolNode
 from .code_node import SymbolScopeNode
 from .code_node import TextNode
+from .code_node import render_code_node
 from .code_node_cxx import CxxClassDefNode
 from .code_node_cxx import CxxFuncDefNode
 from .code_node_cxx import CxxLikelyIfNode
 from .code_node_cxx import CxxUnlikelyIfNode
-from .codegen_utils import render_code_node
+from .codegen_accumulator import CodeGenAccumulator
 from .mako_renderer import MakoRenderer
 
 
@@ -23,6 +24,8 @@
     def assertRenderResult(self, node, expected):
         if node.renderer is None:
             node.set_renderer(MakoRenderer())
+        if node.accumulator is None:
+            node.set_accumulator(CodeGenAccumulator())
 
         def simplify(text):
             return "\n".join(
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
index a5ea6bb..24756d5 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
@@ -9,7 +9,8 @@
 from .code_node import SymbolNode
 from .code_node import SymbolScopeNode
 from .code_node import TextNode
-from .codegen_utils import render_code_node
+from .code_node import render_code_node
+from .codegen_accumulator import CodeGenAccumulator
 from .mako_renderer import MakoRenderer
 
 
@@ -21,6 +22,8 @@
     def assertRenderResult(self, node, expected):
         if node.renderer is None:
             node.set_renderer(MakoRenderer())
+        if node.accumulator is None:
+            node.set_accumulator(CodeGenAccumulator())
 
         def simplify(text):
             return "\n".join(
@@ -135,7 +138,8 @@
             ]))
 
         with self.assertRaises(NameError):
-            root.render()
+            renderer.reset()
+            root.render(renderer)
 
         callers_on_error = list(renderer.callers_on_error)
         self.assertEqual(len(callers_on_error), 3)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
index 7306c534..f72e41a 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
@@ -17,6 +17,10 @@
         # Forward declarations of C++ struct
         self._struct_decls = set()
 
+    def total_size(self):
+        return (len(self.include_headers) + len(self.class_decls) + len(
+            self.struct_decls))
+
     @property
     def include_headers(self):
         return self._include_headers
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
index d8c3295..069f62c 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
@@ -177,16 +177,7 @@
         "Worklet": "IsWorkletGlobalScope",
     }
     exposed_terms = []
-    if global_names is None:
-        for entry in exposure.global_names_and_features:
-            terms = []
-            pred = GLOBAL_NAME_TO_EXECUTION_CONTEXT_TEST[entry.global_name]
-            terms.append(_Expr("${{execution_context}}->{}()".format(pred)))
-            if entry.feature:
-                terms.append(ref_enabled(entry.feature))
-            if terms:
-                exposed_terms.append(expr_and(terms))
-    else:
+    if global_names:
         matched_global_count = 0
         for entry in exposure.global_names_and_features:
             if entry.global_name not in global_names:
@@ -196,6 +187,15 @@
                 exposed_terms.append(ref_enabled(entry.feature))
         assert (not exposure.global_names_and_features
                 or matched_global_count > 0)
+    else:
+        for entry in exposure.global_names_and_features:
+            terms = []
+            pred = GLOBAL_NAME_TO_EXECUTION_CONTEXT_TEST[entry.global_name]
+            terms.append(_Expr("${{execution_context}}->{}()".format(pred)))
+            if entry.feature:
+                terms.append(ref_enabled(entry.feature))
+            if terms:
+                exposed_terms.append(expr_and(terms))
     if exposed_terms:
         top_terms.append(expr_or(exposed_terms))
 
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
index 65ac16c9..7831d11 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
@@ -7,8 +7,10 @@
 from . import name_style
 from .clang_format import clang_format
 from .code_node import CodeNode
+from .code_node import EmptyNode
 from .code_node import LiteralNode
 from .code_node import SequenceNode
+from .code_node import render_code_node
 from .codegen_accumulator import CodeGenAccumulator
 from .path_manager import PathManager
 
@@ -62,6 +64,17 @@
     return name_style.macro(component, "EXPORT")
 
 
+def component_export_header(component):
+    assert isinstance(component, web_idl.Component)
+
+    if component == "core":
+        return "third_party/blink/renderer/core/core_export.h"
+    elif component == "modules":
+        return "third_party/blink/renderer/modules/modules_export.h"
+    else:
+        assert False
+
+
 def enclose_with_header_guard(code_node, header_guard):
     assert isinstance(code_node, CodeNode)
     assert isinstance(header_guard, str)
@@ -69,9 +82,9 @@
     return SequenceNode([
         LiteralNode("#ifndef {}".format(header_guard)),
         LiteralNode("#define {}".format(header_guard)),
-        LiteralNode(""),
+        EmptyNode(),
         code_node,
-        LiteralNode(""),
+        EmptyNode(),
         LiteralNode("#endif  // {}".format(header_guard)),
     ])
 
@@ -82,9 +95,9 @@
 
     return SequenceNode([
         LiteralNode("namespace {} {{".format(namespace)),
-        LiteralNode(""),
+        EmptyNode(),
         code_node,
-        LiteralNode(""),
+        EmptyNode(),
         LiteralNode("}}  // namespace {}".format(namespace)),
     ])
 
@@ -140,24 +153,14 @@
     for type_def_obj in type_def_objs:
         if isinstance(type_def_obj, web_idl.Enumeration):
             continue
-        header_paths.add(PathManager(type_def_obj).blink_path(ext="h"))
+        if isinstance(type_def_obj, web_idl.Dictionary):
+            header_paths.add(PathManager(type_def_obj).dict_path(ext="h"))
+            continue
+        header_paths.add(PathManager(type_def_obj).api_path(ext="h"))
 
     return header_paths
 
 
-def render_code_node(code_node):
-    """
-    Renders |code_node| and turns it into text letting |code_node| apply all
-    necessary changes (side effects).  Returns the resulting text.
-    """
-    prev = "_"
-    current = ""
-    while current != prev:
-        prev = current
-        current = str(code_node)
-    return current
-
-
 def write_code_node_to_file(code_node, filepath):
     """Renders |code_node| and then write the result to |filepath|."""
     assert isinstance(code_node, CodeNode)
@@ -167,5 +170,4 @@
 
     format_result = clang_format(rendered_text, filename=filepath)
 
-    with open(filepath, "w") as output_file:
-        output_file.write(format_result.contents)
+    web_idl.file_io.write_to_file_if_changed(filepath, format_result.contents)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
index fc13087b..ccffd7d 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -14,17 +14,21 @@
 from .code_node import Likeliness
 from .code_node import ListNode
 from .code_node import SequenceNode
+from .code_node import SymbolNode
 from .code_node import SymbolScopeNode
 from .code_node import TextNode
+from .code_node_cxx import CxxClassDefNode
 from .code_node_cxx import CxxFuncDeclNode
 from .code_node_cxx import CxxFuncDefNode
 from .code_node_cxx import CxxIfElseNode
 from .code_node_cxx import CxxLikelyIfNode
+from .code_node_cxx import CxxNamespaceNode
 from .codegen_accumulator import CodeGenAccumulator
 from .codegen_context import CodeGenContext
 from .codegen_expr import expr_from_exposure
 from .codegen_format import format_template as _format
 from .codegen_utils import collect_include_headers
+from .codegen_utils import component_export
 from .codegen_utils import enclose_with_header_guard
 from .codegen_utils import enclose_with_namespace
 from .codegen_utils import make_copyright_header
@@ -88,24 +92,21 @@
     T = TextNode
 
     member = cg_context.dict_member
+    blink_member_name = _blink_member_name(member)
 
-    func_name = T(
-        _format("${class_name}::{}",
-                _blink_member_name(member).get_api))
     func_def = CxxFuncDefNode(
-        name=func_name,
+        name=blink_member_name.get_api,
         arg_decls=[],
         return_type=blink_type_info(member.idl_type).ref_t,
         const=True)
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
 
-    _1 = _blink_member_name(member).has_api
-    body.append(T(_format("DCHECK({_1}());", _1=_1)))
-
-    _1 = _blink_member_name(member).value_var
-    body.append(T(_format("return {_1};", _1=_1)))
+    body.extend([
+        T(_format("DCHECK({}());", blink_member_name.has_api)),
+        T(_format("return {};", blink_member_name.value_var)),
+    ])
 
     return func_def
 
@@ -117,12 +118,12 @@
 
     member = cg_context.dict_member
 
-    func_name = T(
-        _format("${class_name}::{}",
-                _blink_member_name(member).has_api))
     func_def = CxxFuncDefNode(
-        name=func_name, arg_decls=[], return_type="bool", const=True)
-    func_def.add_template_vars(cg_context.template_bindings())
+        name=_blink_member_name(member).has_api,
+        arg_decls=[],
+        return_type="bool",
+        const=True)
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
 
@@ -138,26 +139,24 @@
     T = TextNode
 
     member = cg_context.dict_member
+    blink_member_name = _blink_member_name(member)
 
-    func_name = T(
-        _format("${class_name}::{}",
-                _blink_member_name(member).set_api))
     func_def = CxxFuncDefNode(
-        name=func_name,
+        name=blink_member_name.set_api,
         arg_decls=[
             _format("{} value",
                     blink_type_info(member.idl_type).ref_t)
         ],
         return_type="void")
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
 
-    _1 = _blink_member_name(member).value_var
+    _1 = blink_member_name.value_var
     body.append(T(_format("{_1} = value;", _1=_1)))
 
     if _does_use_presence_flag(member):
-        _1 = _blink_member_name(member).presence_var
+        _1 = blink_member_name.presence_var
         body.append(T(_format("{_1} = true;", _1=_1)))
 
     return func_def
@@ -171,7 +170,8 @@
     dictionary = cg_context.dictionary
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::GetV8MemberNames"),
+        name="GetV8MemberNames",
+        class_name=cg_context.class_name,
         arg_decls=["v8::Isolate* isolate"],
         return_type="const v8::Eternal<v8::Name>*")
     func_def.add_template_vars(cg_context.template_bindings())
@@ -200,7 +200,8 @@
     dictionary = cg_context.dictionary
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::FillWithMembers"),
+        name="FillWithMembers",
+        class_name=cg_context.class_name,
         arg_decls=[
             "v8::Isolate* isolate",
             "v8::Local<v8::Object> creation_context",
@@ -235,7 +236,8 @@
     own_members = dictionary.own_members
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::FillWithOwnMembers"),
+        name="FillWithOwnMembers",
+        class_name=cg_context.class_name,
         arg_decls=[
             "v8::Isolate* isolate",
             "v8::Local<v8::Object> creation_context",
@@ -246,13 +248,17 @@
     func_def.add_template_vars(cg_context.template_bindings())
 
     body = func_def.body
+    body.add_template_var("current_context", "current_context")
+    body.register_code_symbol(
+        SymbolNode(
+            "execution_context", "ExecutionContext* ${execution_context} = "
+            "ToExecutionContext(${current_context});"))
 
     text = """\
 const v8::Eternal<v8::Name>* member_names = GetV8MemberNames(isolate);
-v8::Local<v8::Context> current_context = isolate->GetCurrentContext();"""
+v8::Local<v8::Context> ${current_context} = isolate->GetCurrentContext();"""
     body.append(T(text))
 
-    # TODO(peria): Support runtime enabled / origin trial members.
     for key_index, member in enumerate(own_members):
         _1 = _blink_member_name(member).has_api
         _2 = key_index
@@ -261,7 +267,7 @@
 if ({_1}()) {{
   if (!v8_dictionary
            ->CreateDataProperty(
-               current_context,
+               ${current_context},
                member_names[{_2}].Get(isolate),
                ToV8({_3}(), creation_context, isolate))
            .ToChecked()) {{
@@ -290,7 +296,8 @@
     dictionary = cg_context.dictionary
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::Create"),
+        name="Create",
+        class_name=cg_context.class_name,
         arg_decls=[
             "v8::Isolate* isolate",
             "v8::Local<v8::Object> v8_dictionary",
@@ -324,7 +331,8 @@
         member for member in own_members if member.is_required)
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::FillMembers"),
+        name="FillMembers",
+        class_name=cg_context.class_name,
         arg_decls=[
             "v8::Isolate* isolate",
             "v8::Local<v8::Object> v8_dictionary",
@@ -378,7 +386,8 @@
     own_members = dictionary.own_members
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::FillMembersInternal"),
+        name="FillMembersInternal",
+        class_name=cg_context.class_name,
         arg_decls=[
             "v8::Isolate* isolate",
             "v8::Local<v8::Object> v8_dictionary",
@@ -390,6 +399,11 @@
     body = func_def.body
     body.add_template_var("isolate", "isolate")
     body.add_template_var("exception_state", "exception_state")
+    body.add_template_var("current_context", "current_context")
+    body.register_code_symbol(
+        SymbolNode(
+            "execution_context", "ExecutionContext* ${execution_context} = "
+            "ToExecutionContext(${current_context});"))
 
     if dictionary.inherited:
         text = """\
@@ -404,12 +418,11 @@
         T("const v8::Eternal<v8::Name>* member_names = "
           "GetV8MemberNames(${isolate});"),
         T("v8::TryCatch try_block(${isolate});"),
-        T("v8::Local<v8::Context> current_context = "
+        T("v8::Local<v8::Context> ${current_context} = "
           "${isolate}->GetCurrentContext();"),
         T("v8::Local<v8::Value> v8_value;"),
     ])
 
-    # TODO(peria): Support origin-trials and runtime enabled features.
     for key_index, member in enumerate(own_members):
         body.append(make_fill_own_dict_member(key_index, member))
 
@@ -423,7 +436,7 @@
     T = TextNode
 
     pattern = """
-if (!v8_dictionary->Get(current_context, member_names[{_1}].Get(${isolate}))
+if (!v8_dictionary->Get(${current_context}, member_names[{_1}].Get(${isolate}))
          .ToLocal(&v8_memer)) {{
   ${exception_state}.RethrowV8Exception(try_block.Exception());
   return;
@@ -475,7 +488,8 @@
     own_members = dictionary.own_members
 
     func_def = CxxFuncDefNode(
-        name=T("${class_name}::Trace"),
+        name="Trace",
+        class_name=cg_context.class_name,
         arg_decls=["Visitor* visitor"],
         return_type="void")
     func_def.add_template_vars(cg_context.template_bindings())
@@ -502,16 +516,24 @@
     T = TextNode
 
     dictionary = cg_context.dictionary
+    component = dictionary.components[0]
 
-    alias_base_class_node = None
+    class_def = CxxClassDefNode(
+        cg_context.class_name,
+        base_class_names=[cg_context.base_class_name],
+        export=component_export(component))
+    class_def.set_base_template_vars(cg_context.template_bindings())
+
     if dictionary.inherited:
-        alias_base_class_node = T("using BaseClass = ${base_class_name};")
+        class_def.top_section.append(
+            TextNode("using BaseClass = ${base_class_name};"))
 
-    public_node = ListNode()
-
-    public_node.append(
+    public_section = class_def.public_section
+    public_section.append(
         T("""\
-static ${class_name}* Create();
+static ${class_name}* Create() {
+  return MakeGarbageCollected<${class_name}>();
+}
 static ${class_name}* Create(
     v8::Isolate* isolate,
     v8::Local<v8::Object> v8_dictionary,
@@ -522,30 +544,17 @@
 void Trace(Visitor* visitor);
 """))
 
-    # TODO(peria): Consider inlining these accessors.
     for member in dictionary.own_members:
-        member_blink_type = blink_type_info(member.idl_type)
-        public_node.append(
-            CxxFuncDeclNode(
-                name=_blink_member_name(member).get_api,
-                return_type=member_blink_type.ref_t,
-                arg_decls=[],
-                const=True))
-        public_node.append(
-            CxxFuncDeclNode(
-                name=_blink_member_name(member).set_api,
-                arg_decls=[_format("{} value", member_blink_type.ref_t)],
-                return_type="void"))
-        public_node.append(
-            CxxFuncDeclNode(
-                name=_blink_member_name(member).has_api,
-                arg_decls=[],
-                return_type="bool",
-                const=True))
+        member_cg_context = cg_context.make_copy(dict_member=member)
+        public_section.extend([
+            T(""),
+            make_dict_member_get_def(member_cg_context),
+            make_dict_member_has_def(member_cg_context),
+            make_dict_member_set_def(member_cg_context),
+        ])
 
-    protected_node = ListNode()
-
-    protected_node.append(
+    protected_section = class_def.protected_section
+    protected_section.append(
         T("""\
 bool FillWithMembers(
     v8::Isolate* isolate,
@@ -553,9 +562,8 @@
     v8::Local<v8::Object> v8_dictionary) const override;
 """))
 
-    private_node = ListNode()
-
-    private_node.append(
+    private_section = class_def.private_section
+    private_section.append(
         T("""\
 static const v8::Eternal<v8::Name>* GetV8MemberNames(v8::Isolate*);
 
@@ -579,158 +587,132 @@
     for member in dictionary.own_members:
         _1 = blink_type_info(member.idl_type).member_t
         _2 = _blink_member_name(member).value_var
-        private_node.append(T(_format("{_1} {_2};", _1=_1, _2=_2)))
+        private_section.append(T(_format("{_1} {_2};", _1=_1, _2=_2)))
 
-    private_node.append(T(""))
+    private_section.append(T(""))
     # C++ member variables for precences
     for member in dictionary.own_members:
         if _does_use_presence_flag(member):
             _1 = _blink_member_name(member).presence_var
-            private_node.append(T(_format("bool {_1} = false;", _1=_1)))
+            private_section.append(T(_format("bool {_1} = false;", _1=_1)))
 
-    node = ListNode()
-    node.add_template_vars(cg_context.template_bindings())
-
-    node.extend([
-        T("class ${class_name} : public ${base_class_name} {"),
-        alias_base_class_node,
-        T("public:"),
-        public_node,
-        T(""),
-        T("protected:"),
-        protected_node,
-        T(""),
-        T("private:"),
-        private_node,
-        T("};"),
-    ])
-
-    return node
+    return class_def
 
 
-def generate_dictionary_cc_file(dictionary):
-    class_name = blink_class_name(dictionary)
-    base_class_name = (blink_class_name(dictionary.inherited)
-                       if dictionary.inherited else "bindings::DictionaryBase")
+def generate_dictionary(dictionary):
+    assert len(dictionary.components) == 1, (
+        "We don't support partial dictionaries across components yet.")
+
+    path_manager = PathManager(dictionary)
+    class_name = name_style.class_(blink_class_name(dictionary))
+    if dictionary.inherited:
+        base_class_name = blink_class_name(dictionary.inherited)
+    else:
+        base_class_name = "bindings::DictionaryBase"
+
     cg_context = CodeGenContext(
         dictionary=dictionary,
         class_name=class_name,
         base_class_name=base_class_name)
 
-    code_node = ListNode()
-    code_node.extend([
-        TextNode("// static"),
-        make_get_v8_dict_member_names_def(cg_context),
-        TextNode("// static"),
-        make_dict_create_def(cg_context),
-        make_fill_dict_members_def(cg_context),
-        make_fill_dict_members_internal_def(cg_context),
-        make_fill_with_dict_members_def(cg_context),
-        make_fill_with_own_dict_members_def(cg_context),
-        make_dict_trace_def(cg_context),
+    # Filepaths
+    header_path = path_manager.dict_path(ext="h")
+    source_path = path_manager.dict_path(ext="cc")
+
+    # Root nodes
+    header_node = ListNode(tail="\n")
+    header_node.set_accumulator(CodeGenAccumulator())
+    header_node.set_renderer(MakoRenderer())
+    source_node = ListNode(tail="\n")
+    source_node.set_accumulator(CodeGenAccumulator())
+    source_node.set_renderer(MakoRenderer())
+
+    # Namespaces
+    header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+    source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+
+    # Class definitions
+    class_def = make_dict_class_def(cg_context)
+
+    # Header part (copyright, include directives, and forward declarations)
+    if dictionary.inherited:
+        # TODO(crbug.com/1034398): Use api_path() or impl_path() once we
+        # migrate IDL compiler and move generated code of dictionaries.
+        base_class_header = PathManager(
+            dictionary.inherited).dict_path(ext="h")
+    else:
+        base_class_header = (
+            "third_party/blink/renderer/platform/bindings/dictionary_base.h")
+    header_node.accumulator.add_include_headers(
+        collect_include_headers(dictionary))
+    header_node.accumulator.add_include_headers([
+        base_class_header,
+        "v8/include/v8.h",
     ])
-
-    for member in dictionary.own_members:
-        code_node.extend([
-            make_dict_member_get_def(cg_context.make_copy(dict_member=member)),
-            make_dict_member_has_def(cg_context.make_copy(dict_member=member)),
-            make_dict_member_set_def(cg_context.make_copy(dict_member=member)),
-        ])
-
-    root_node = ListNode(tail="\n")
-    root_node.set_accumulator(CodeGenAccumulator())
-    root_node.set_renderer(MakoRenderer())
-
-    # TODO(crbug.com/1034398): Use api_path() or impl_path() once we migrate
-    # IDL compiler and move generated code of dictionaries.
-    h_file_path = PathManager(dictionary).dict_path(ext="h")
-
-    root_node.accumulator.add_include_headers([
+    header_node.accumulator.add_class_decls([
+        "ExceptionState",
+        "Visitor",
+    ])
+    source_node.accumulator.add_include_headers([
         "third_party/blink/renderer/platform/bindings/exception_messages.h",
         "third_party/blink/renderer/platform/bindings/exception_state.h",
         "third_party/blink/renderer/platform/heap/visitor.h",
         "v8/include/v8.h",
     ])
 
-    root_node.extend([
+    header_node.extend([
         make_copyright_header(),
         TextNode(""),
-        TextNode(_format("#include \"{}\"", h_file_path)),
-        TextNode(""),
-        make_header_include_directives(root_node.accumulator),
-        TextNode(""),
-        enclose_with_namespace(code_node, name_style.namespace("blink")),
+        enclose_with_header_guard(
+            ListNode([
+                make_header_include_directives(header_node.accumulator),
+                TextNode(""),
+                header_blink_ns,
+            ]), name_style.header_guard(header_path)),
     ])
-
-    filepath = PathManager.gen_path_to(
-        PathManager(dictionary).dict_path(ext="cc"))
-    write_code_node_to_file(root_node, filepath)
-
-
-def generate_dictionary_h_file(dictionary):
-    class_name = blink_class_name(dictionary)
-    base_class_name = (blink_class_name(dictionary.inherited)
-                       if dictionary.inherited else "bindings::DictionaryBase")
-    cg_context = CodeGenContext(
-        dictionary=dictionary,
-        class_name=class_name,
-        base_class_name=base_class_name)
-
-    code_node = ListNode()
-    code_node.extend([
-        make_dict_class_def(cg_context),
+    header_blink_ns.body.extend([
+        make_forward_declarations(header_node.accumulator),
+        TextNode(""),
     ])
-
-    root_node = ListNode(tail="\n")
-    root_node.set_accumulator(CodeGenAccumulator())
-    root_node.set_renderer(MakoRenderer())
-
-    root_node.accumulator.add_include_headers(
+    source_node.extend([
+        make_copyright_header(),
+        TextNode(""),
+        TextNode("#include \"{}\"".format(header_path)),
+        TextNode(""),
+        make_header_include_directives(source_node.accumulator),
+        TextNode(""),
+        source_blink_ns,
+    ])
+    source_blink_ns.body.extend([
+        make_forward_declarations(source_node.accumulator),
+        TextNode(""),
+    ])
+    source_node.accumulator.add_include_headers(
         collect_include_headers(dictionary))
-    base_class_header = (
-        "third_party/blink/renderer/platform/bindings/dictionary_base.h")
-    if dictionary.inherited:
-        # TODO(crbug.com/1034398): Use api_path() or impl_path() once we
-        # migrate IDL compiler and move generated code of dictionaries.
-        base_class_header = PathManager(
-            dictionary.inherited).dict_path(ext="h")
-    root_node.accumulator.add_include_headers([
-        base_class_header,
-        "v8/include/v8.h",
-    ])
-    root_node.accumulator.add_class_decls([
-        "ExceptionState",
-        "Visitor",
-    ])
 
-    namespace_node = enclose_with_namespace(
-        ListNode([
-            make_forward_declarations(root_node.accumulator),
-            TextNode(""),
-            code_node,
-        ]), name_style.namespace("blink"))
-
-    header_guard = name_style.header_guard(
-        PathManager(dictionary).dict_path(ext="h"))
-    header_guard_node = enclose_with_header_guard(
-        ListNode([
-            make_header_include_directives(root_node.accumulator),
-            TextNode(""),
-            namespace_node,
-        ]), header_guard)
-
-    root_node.extend([
-        make_copyright_header(),
+    # Assemble the parts.
+    header_blink_ns.body.append(class_def)
+    source_blink_ns.body.extend([
+        make_get_v8_dict_member_names_def(cg_context),
         TextNode(""),
-        header_guard_node,
+        make_dict_create_def(cg_context),
+        TextNode(""),
+        make_fill_dict_members_def(cg_context),
+        TextNode(""),
+        make_fill_dict_members_internal_def(cg_context),
+        TextNode(""),
+        make_fill_with_dict_members_def(cg_context),
+        TextNode(""),
+        make_fill_with_own_dict_members_def(cg_context),
+        TextNode(""),
+        make_dict_trace_def(cg_context),
     ])
 
-    filepath = PathManager.gen_path_to(
-        PathManager(dictionary).dict_path(ext="h"))
-    write_code_node_to_file(root_node, filepath)
+    # Write down to the files.
+    write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+    write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
 
 
 def generate_dictionaries(web_idl_database):
     for dictionary in web_idl_database.dictionaries:
-        generate_dictionary_cc_file(dictionary)
-        generate_dictionary_h_file(dictionary)
+        generate_dictionary(dictionary)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index 74f9ada..dbe02e9 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -13,6 +13,7 @@
 from .blink_v8_bridge import make_v8_to_blink_value
 from .blink_v8_bridge import make_v8_to_blink_value_variadic
 from .blink_v8_bridge import v8_bridge_class_name
+from .code_node import EmptyNode
 from .code_node import ListNode
 from .code_node import SequenceNode
 from .code_node import SymbolDefinitionNode
@@ -36,6 +37,7 @@
 from .codegen_format import format_template as _format
 from .codegen_utils import collect_include_headers
 from .codegen_utils import component_export
+from .codegen_utils import component_export_header
 from .codegen_utils import enclose_with_header_guard
 from .codegen_utils import make_copyright_header
 from .codegen_utils import make_forward_declarations
@@ -521,7 +523,7 @@
             # [ReflectOnly]
             node = _make_reflect_process_keyword_state(cg_context)
             if node:
-                nodes.append(T(""))
+                nodes.append(EmptyNode())
                 nodes.append(node)
 
         return SymbolDefinitionNode(symbol_node, nodes)
@@ -929,7 +931,7 @@
 
     return SequenceNode([
         branches,
-        T(""),
+        EmptyNode(),
         T("${exception_state}.ThrowTypeError"
           "(\"Overload resolution failed.\");\n"
           "return;"),
@@ -1089,7 +1091,7 @@
 
     node = TextNode(
         _format(
-            "{macro_name}(${isolate}, {counter_name})",
+            "{macro_name}(${isolate}, {counter_name});",
             macro_name=macro_name,
             counter_name=counter_name))
     node.accumulate(
@@ -1176,9 +1178,9 @@
     T = TextNode
 
     if cg_context.attribute_set or cg_context.return_type.unwrap().is_void:
-        # Render a SymbolNode |return_value| discarding the content text, and
-        # let a symbol definition be inserted.
-        return T("<% str(return_value) %>")
+        # Request a SymbolNode |return_value| to define itself without rendering
+        # any text.
+        return T("<% return_value.request_symbol_definition() %>")
 
     return_type_body = cg_context.return_type.unwrap()
     if (cg_context.for_world == cg_context.MAIN_WORLD
@@ -1201,7 +1203,7 @@
 
     func_def = CxxFuncDefNode(
         name=function_name, arg_decls=arg_decls, return_type="void")
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
     body.add_template_var("info", "info")
@@ -1226,10 +1228,10 @@
         make_report_deprecate_as(cg_context),
         make_report_measure_as(cg_context),
         make_log_activity(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_check_receiver(cg_context),
         make_return_value_cache_return_early(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_check_security_of_return_value(cg_context),
         make_v8_set_return_value(cg_context),
         make_return_value_cache_update_value(cg_context),
@@ -1260,10 +1262,10 @@
         make_report_deprecate_as(cg_context),
         make_report_measure_as(cg_context),
         make_log_activity(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_check_receiver(cg_context),
         make_check_argument_length(cg_context),
-        TextNode(""),
+        EmptyNode(),
     ])
 
     if "PutForwards" in ext_attrs:
@@ -1276,7 +1278,7 @@
 
     body.extend([
         make_steps_of_ce_reactions(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_v8_set_return_value(cg_context),
     ])
 
@@ -1310,7 +1312,7 @@
     body.extend([
         make_runtime_call_timer_scope(cg_context),
         logging_nodes,
-        TextNode(""),
+        EmptyNode(),
         TextNode(v8_set_return_value),
     ])
 
@@ -1338,11 +1340,11 @@
 
     if cg_context.operation_group:
         body.append(make_cooperative_scheduling_safepoint(cg_context))
-        body.append(TextNode(""))
+        body.append(EmptyNode())
 
     if cg_context.constructor_group:
         body.append(make_check_constructor_call(cg_context))
-        body.append(TextNode(""))
+        body.append(EmptyNode())
 
     body.append(make_overload_dispatcher(cg_context))
 
@@ -1363,7 +1365,7 @@
         make_report_deprecate_as(cg_context),
         make_report_measure_as(cg_context),
         make_log_activity(cg_context),
-        T(""),
+        EmptyNode(),
     ])
 
     if "HTMLConstructor" in cg_context.constructor.extended_attributes:
@@ -1401,7 +1403,7 @@
         node.extend([
             make_constructor_function_def(
                 cgc, callback_function_name(cgc, constructor.overload_index)),
-            TextNode(""),
+            EmptyNode(),
         ])
     node.append(
         make_overload_dispatcher_function_def(cg_context, function_name))
@@ -1429,7 +1431,7 @@
         make_report_deprecate_as(cg_context),
         make_report_measure_as(cg_context),
         make_log_activity(cg_context),
-        TextNode(""),
+        EmptyNode(),
         TextNode(v8_set_return_value),
     ])
 
@@ -1448,11 +1450,11 @@
         make_report_deprecate_as(cg_context),
         make_report_measure_as(cg_context),
         make_log_activity(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_check_receiver(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_steps_of_ce_reactions(cg_context),
-        TextNode(""),
+        EmptyNode(),
         make_check_security_of_return_value(cg_context),
         make_v8_set_return_value(cg_context),
     ])
@@ -1476,7 +1478,7 @@
         node.extend([
             make_operation_function_def(
                 cgc, callback_function_name(cgc, operation.overload_index)),
-            TextNode(""),
+            EmptyNode(),
         ])
     node.append(
         make_overload_dispatcher_function_def(cg_context, function_name))
@@ -1948,9 +1950,9 @@
 
         callback_def_nodes.extend([
             attr_get_callback_node,
-            TextNode(""),
+            EmptyNode(),
             attr_set_callback_node,
-            TextNode(""),
+            EmptyNode(),
         ])
 
         attribute_entries.append(
@@ -1975,7 +1977,7 @@
 
         callback_def_nodes.extend([
             const_callback_node,
-            TextNode(""),
+            EmptyNode(),
         ])
 
         constant_entries.append(
@@ -1997,7 +1999,7 @@
 
         callback_def_nodes.extend([
             ctor_callback_node,
-            TextNode(""),
+            EmptyNode(),
         ])
 
         constructor_entries.append(
@@ -2020,7 +2022,7 @@
 
         callback_def_nodes.extend([
             prop_callback_node,
-            TextNode(""),
+            EmptyNode(),
         ])
 
         exposed_construct_entries.append(
@@ -2040,7 +2042,7 @@
 
         callback_def_nodes.extend([
             op_callback_node,
-            TextNode(""),
+            EmptyNode(),
         ])
 
         operation_entries.append(
@@ -2117,7 +2119,7 @@
         class_name=class_name,
         arg_decls=arg_decls,
         return_type=return_type)
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
     body.add_template_vars({
@@ -2132,7 +2134,7 @@
           "${isolate}, ${interface_template}, "
           "${wrapper_type_info}->interface_name, ${parent_interface_template}, "
           "kV8DefaultWrapperInternalFieldCount);"),
-        T(""),
+        EmptyNode(),
     ])
 
     for entry in constructor_entries:
@@ -2154,7 +2156,7 @@
             body.extend([T(set_callback), T(set_length)])
         else:
             assert False
-    body.append(T(""))
+    body.append(EmptyNode())
 
     if ("Global" in cg_context.class_like.extended_attributes
             or cg_context.class_like.identifier == "Location"):
@@ -2165,7 +2167,7 @@
         body.extend([
             T("${instance_template}->SetImmutableProto();"),
             T("${prototype_template}->SetImmutableProto();"),
-            T(""),
+            EmptyNode(),
         ])
 
     func_call_pattern = ("{}(${isolate}, ${world}, ${instance_template}, "
@@ -2219,7 +2221,7 @@
 
     if is_context_dependent:
         arg_decls = [
-            "v8::Local<v8::Content> context",
+            "v8::Local<v8::Context> context",
             "const DOMWrapperWorld& world",
             "v8::Local<v8::Object> instance_object",
             "v8::Local<v8::Object> prototype_object",
@@ -2276,7 +2278,7 @@
         class_name=class_name,
         arg_decls=arg_decls,
         return_type=return_type)
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
     if is_context_dependent:
@@ -2319,7 +2321,7 @@
                     make_table_func(table_name, unconditional_entries),
                     TextNode(installer_call_text),
                 ]))
-            body.append(TextNode(""))
+            body.append(EmptyNode())
         for conditional, entries in conditional_to_entries.iteritems():
             body.append(
                 CxxUnlikelyIfNode(
@@ -2328,7 +2330,7 @@
                         make_table_func(table_name, entries),
                         TextNode(installer_call_text),
                     ]))
-        body.append(TextNode(""))
+        body.append(EmptyNode())
 
     table_name = "kAttributeTable"
     if is_context_dependent:
@@ -2447,7 +2449,7 @@
         class_name=class_name,
         arg_decls=[],
         return_type="void")
-    func_def.add_template_vars(cg_context.template_bindings())
+    func_def.set_base_template_vars(cg_context.template_bindings())
 
     body = func_def.body
     body.extend([
@@ -2478,7 +2480,7 @@
     # Class names
     api_class_name = v8_bridge_class_name(interface)
     if is_cross_components:
-        impl_class_name = name_style.class_(api_class_name, "impl")
+        impl_class_name = "{}::Impl".format(api_class_name)
     else:
         impl_class_name = api_class_name
 
@@ -2509,11 +2511,6 @@
     else:
         impl_header_node = api_header_node
         impl_source_node = api_source_node
-    api_header_node.add_template_var("impl_class_name", impl_class_name)
-    api_source_node.add_template_var("impl_class_name", impl_class_name)
-    if is_cross_components:
-        impl_header_node.add_template_var("impl_class_name", impl_class_name)
-        impl_source_node.add_template_var("impl_class_name", impl_class_name)
 
     # Namespaces
     api_header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
@@ -2528,20 +2525,24 @@
     # Class definitions
     api_class_def = CxxClassDefNode(
         cg_context.class_name,
+        base_class_names=[
+            _format("bindings::V8InterfaceBridge<${class_name}, {}>",
+                    blink_class_name(interface)),
+        ],
         final=True,
         export=component_export(api_component))
-    api_class_def.add_template_vars(cg_context.template_bindings())
-    api_class_def.top_section.append(TextNode("STATIC_ONLY(${class_name});"))
+    api_class_def.set_base_template_vars(cg_context.template_bindings())
     if is_cross_components:
-        api_class_def.bottom_section.append(
-            TextNode("friend class ${impl_class_name};"))
         impl_class_def = CxxClassDefNode(
             impl_class_name,
             final=True,
             export=component_export(impl_component))
-        impl_class_def.add_template_vars(cg_context.template_bindings())
-        impl_class_def.top_section.append(
-            TextNode("STATIC_ONLY(${impl_class_name});"))
+        impl_class_def.set_base_template_vars(cg_context.template_bindings())
+        api_class_def.public_section.extend([
+            TextNode("// Cross-component implementation class"),
+            TextNode("class Impl;"),
+            EmptyNode(),
+        ])
     else:
         impl_class_def = api_class_def
 
@@ -2645,11 +2646,11 @@
     ])
     installer_function_defs = ListNode([
         install_interface_template_def,
-        TextNode(""),
+        EmptyNode(),
         install_unconditional_props_def,
-        TextNode(""),
+        EmptyNode(),
         install_context_independent_props_def,
-        TextNode(""),
+        EmptyNode(),
         install_context_dependent_props_def,
     ])
     installer_function_trampolines = ListNode([
@@ -2662,64 +2663,75 @@
     # Header part (copyright, include directives, and forward declarations)
     api_header_node.extend([
         make_copyright_header(),
-        TextNode(""),
+        EmptyNode(),
         enclose_with_header_guard(
             ListNode([
                 make_header_include_directives(api_header_node.accumulator),
-                TextNode(""),
+                EmptyNode(),
                 api_header_blink_ns,
             ]), name_style.header_guard(api_header_path)),
     ])
     api_header_blink_ns.body.extend([
         make_forward_declarations(api_header_node.accumulator),
-        TextNode(""),
+        EmptyNode(),
     ])
     api_source_node.extend([
         make_copyright_header(),
-        TextNode(""),
+        EmptyNode(),
         TextNode("#include \"{}\"".format(api_header_path)),
-        TextNode(""),
+        EmptyNode(),
         make_header_include_directives(api_source_node.accumulator),
-        TextNode(""),
+        EmptyNode(),
         api_source_blink_ns,
     ])
     api_source_blink_ns.body.extend([
         make_forward_declarations(api_source_node.accumulator),
-        TextNode(""),
+        EmptyNode(),
     ])
     if is_cross_components:
         impl_header_node.extend([
             make_copyright_header(),
-            TextNode(""),
+            EmptyNode(),
             enclose_with_header_guard(
                 ListNode([
                     make_header_include_directives(
                         impl_header_node.accumulator),
-                    TextNode(""),
+                    EmptyNode(),
                     impl_header_blink_ns,
                 ]), name_style.header_guard(impl_header_path)),
         ])
         impl_header_blink_ns.body.extend([
             make_forward_declarations(impl_header_node.accumulator),
-            TextNode(""),
+            EmptyNode(),
         ])
         impl_source_node.extend([
             make_copyright_header(),
-            TextNode(""),
+            EmptyNode(),
             TextNode("#include \"{}\"".format(impl_header_path)),
-            TextNode(""),
+            EmptyNode(),
             make_header_include_directives(impl_source_node.accumulator),
-            TextNode(""),
+            EmptyNode(),
             impl_source_blink_ns,
         ])
         impl_source_blink_ns.body.extend([
             make_forward_declarations(impl_source_node.accumulator),
-            TextNode(""),
+            EmptyNode(),
         ])
+    api_header_node.accumulator.add_include_headers([
+        component_export_header(api_component),
+        "third_party/blink/renderer/platform/bindings/v8_interface_bridge.h",
+    ])
+    api_header_node.accumulator.add_class_decl(blink_class_name(interface))
+    if is_cross_components:
+        impl_header_node.accumulator.add_include_headers([
+            api_header_path,
+            component_export_header(impl_component),
+        ])
+    impl_source_node.accumulator.add_include_headers([
+        path_manager.blink_path(ext="h"),
+    ])
     impl_source_node.accumulator.add_include_headers(
         collect_include_headers(interface))
-    if is_cross_components:
-        impl_source_node.accumulator.add_include_header(api_header_path)
 
     # Assemble the parts.
     api_header_blink_ns.body.append(api_class_def)
@@ -2729,25 +2741,22 @@
     if is_cross_components:
         api_class_def.public_section.append(installer_function_trampolines)
         api_class_def.private_section.append(trampoline_var_defs)
-        impl_class_def.public_section.extend([
-            cross_component_init_decl,
-            TextNode(""),
-            installer_function_decls,
-        ])
+        impl_class_def.public_section.append(cross_component_init_decl)
+        impl_class_def.private_section.append(installer_function_decls)
         impl_source_blink_ns.body.extend([
             cross_component_init_def,
-            TextNode(""),
+            EmptyNode(),
         ])
     else:
         api_class_def.public_section.append(installer_function_decls)
 
     if constant_defs:
-        api_class_def.public_section.append(TextNode(""))
+        api_class_def.public_section.append(EmptyNode())
         api_class_def.public_section.append(constant_defs)
 
     impl_source_blink_ns.body.extend([
         CxxNamespaceNode(name="", body=callback_defs),
-        TextNode(""),
+        EmptyNode(),
         installer_function_defs,
     ])
 
@@ -2764,5 +2773,5 @@
 
 
 def generate_interfaces(web_idl_database):
-    interface = web_idl_database.find("Window")
+    interface = web_idl_database.find("Navigator")
     generate_interface(interface)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py b/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
index f99a03be..68554b5 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
@@ -4,7 +4,9 @@
 
 import sys
 
+import mako.runtime
 import mako.template
+import mako.util
 
 
 _MAKO_TEMPLATE_PASS_KEY = object()
@@ -38,9 +40,31 @@
     """Represents a renderer object implemented with Mako templates."""
 
     def __init__(self):
+        self._text_buffer = None
+        self._is_invalidated = False
         self._caller_stack = []
         self._caller_stack_on_error = []
 
+    def reset(self):
+        """
+        Resets the rendering states of this object.  Must be called before
+        the first call to |render| or |render_text|.
+        """
+        self._text_buffer = mako.util.FastEncodingBuffer()
+        self._is_invalidated = False
+
+    def is_rendering_complete(self):
+        return not (self._is_invalidated or self._text_buffer is None
+                    or self._caller_stack)
+
+    def invalidate_rendering_result(self):
+        self._is_invalidated = True
+
+    def to_text(self):
+        """Returns the rendering result."""
+        assert self._text_buffer is not None
+        return self._text_buffer.getvalue()
+
     def render(self, caller, template, template_vars):
         """
         Renders the template with variable bindings.
@@ -63,7 +87,9 @@
         try:
             mako_template = template.mako_template(
                 pass_key=_MAKO_TEMPLATE_PASS_KEY)
-            text = mako_template.render(**template_vars)
+            mako_context = mako.runtime.Context(self._text_buffer,
+                                                **template_vars)
+            mako_template.render_context(mako_context)
         except:
             # Print stacktrace of template rendering.
             sys.stderr.write("\n")
@@ -89,7 +115,16 @@
         finally:
             self._caller_stack.pop()
 
-        return text
+    def render_text(self, text):
+        """Renders a plain text as is."""
+        assert isinstance(text, str)
+        self._text_buffer.write(text)
+
+    def push_caller(self, caller):
+        self._caller_stack.append(caller)
+
+    def pop_caller(self):
+        self._caller_stack.pop()
 
     @property
     def callers_from_first_to_last(self):
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
index 4dacc398..a2fb2b2 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
@@ -29,6 +29,7 @@
 _setup_sys_path()
 
 
+from . import file_io
 from .ast_group import AstGroup
 from .attribute import Attribute
 from .callback_function import CallbackFunction
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py b/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
index 9136a41a3..a480c3fb 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
@@ -10,7 +10,7 @@
     """
     Reads the content of the file as a pickled object.
     """
-    with open(filepath, 'r') as file_obj:
+    with open(filepath, 'rb') as file_obj:
         return pickle.load(file_obj)
 
 
@@ -30,7 +30,7 @@
     Returns True if the data is written to the file, and False if skipped.
     """
     try:
-        with open(filepath, 'r') as file_obj:
+        with open(filepath, 'rb') as file_obj:
             old_contents = file_obj.read()
     except (OSError, EnvironmentError):
         pass
@@ -38,6 +38,10 @@
         if contents == old_contents:
             return False
         os.remove(filepath)
-    with open(filepath, 'w') as file_obj:
+
+    if not os.path.exists(os.path.dirname(filepath)):
+        os.makedirs(os.path.dirname(filepath))
+
+    with open(filepath, 'wb') as file_obj:
         file_obj.write(contents)
     return True
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
index 97133e3..0b5fdfe 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -232,6 +232,7 @@
         Args:
             nullable:
             typedef:
+            variadic:
                 All these arguments take tri-state value: True, False, or None.
                 True unwraps that type, False stops unwrapping that type.  All
                 of specified arguments' values must be consistent, and mixture
@@ -681,6 +682,9 @@
     def __hash__(self):
         return hash(self.identifier)
 
+    def _unwrap(self, switches):
+        return self.target_object._unwrap(switches)
+
 
 class DefinitionType(IdlType, WithIdentifier):
     """
diff --git a/third_party/blink/renderer/build/scripts/core/css/css_properties.py b/third_party/blink/renderer/build/scripts/core/css/css_properties.py
index 928e6b0c..b6b40d0d 100755
--- a/third_party/blink/renderer/build/scripts/core/css/css_properties.py
+++ b/third_party/blink/renderer/build/scripts/core/css/css_properties.py
@@ -265,6 +265,7 @@
         set_if_none(property_, 'setter', 'Set' + method_name)
         if property_['inherited']:
             property_['is_inherited_setter'] = 'Set' + method_name + 'IsInherited'
+        property_['is_animation_property'] = property_['priority'] == 'Animation'
 
         # Figure out whether this property should have style builders at all.
         # E.g. shorthands do not get style builders.
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
index 02df45d..2e5a839 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
@@ -41,6 +41,7 @@
   (property.is_internal and 'kInternal' or ''),
   (property.affected_by_forced_colors and 'kIsAffectedByForcedColors' or ''),
   (property.ua and 'kUA' or ''),
+  (property.is_animation_property and 'kAnimation' or ''),
 ] | reject('==', '') | join(' | ') %}
 {% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %}
 // {{property.name}}
diff --git a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
index 2f55ee0..af72365 100644
--- a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
@@ -102,6 +102,15 @@
                            state.ParentStyle()->EffectiveZoom());
 }
 
+class AlwaysInvalidateChecker
+    : public CSSInterpolationType::CSSConversionChecker {
+ public:
+  bool IsValid(const StyleResolverState& state,
+               const InterpolationValue& underlying) const final {
+    return false;
+  }
+};
+
 InterpolationValue CSSShadowListInterpolationType::MaybeConvertValue(
     const CSSValue& value,
     const StyleResolverState*,
@@ -147,13 +156,9 @@
     double underlying_fraction,
     const InterpolationValue& value,
     double interpolation_fraction) const {
-  ListInterpolationFunctions::Composite(
-      underlying_value_owner, underlying_fraction, *this, value,
-      ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest,
-      WTF::BindRepeating(InterpolableShadow::CompatibleForCompositing),
-      WTF::BindRepeating(
-          ListInterpolationFunctions::VerifyNoNonInterpolableValues),
-      WTF::BindRepeating(InterpolableShadow::Composite));
+  // We do our compositing behavior in |PreInterpolationCompositeIfNeeded|; see
+  // the documentation on that method.
+  underlying_value_owner.Set(*this, value);
 }
 
 static scoped_refptr<ShadowList> CreateShadowList(
@@ -190,4 +195,86 @@
   }
 }
 
+InterpolationValue
+CSSShadowListInterpolationType::PreInterpolationCompositeIfNeeded(
+    InterpolationValue value,
+    const InterpolationValue& underlying,
+    EffectModel::CompositeOperation composite,
+    ConversionCheckers& conversion_checkers) const {
+  // Due to the post-interpolation composite optimization, the interpolation
+  // stack aggressively caches interpolated values. When we are doing
+  // pre-interpolation compositing, this can cause us to bake-in the composited
+  // result even when the underlying value is changing. This checker is a hack
+  // to disable that caching in this case.
+  // TODO(crbug.com/1009230): Remove this once our interpolation code isn't
+  // caching composited values.
+  conversion_checkers.push_back(std::make_unique<AlwaysInvalidateChecker>());
+  auto interpolable_list = std::unique_ptr<InterpolableList>(
+      To<InterpolableList>(value.interpolable_value.release()));
+  if (composite == EffectModel::CompositeOperation::kCompositeAdd) {
+    return PerformAdditiveComposition(std::move(interpolable_list), underlying);
+  }
+  DCHECK_EQ(composite, EffectModel::CompositeOperation::kCompositeAccumulate);
+  return PerformAccumulativeComposition(std::move(interpolable_list),
+                                        std::move(underlying));
+}
+
+InterpolationValue CSSShadowListInterpolationType::PerformAdditiveComposition(
+    std::unique_ptr<InterpolableList> interpolable_list,
+    const InterpolationValue& underlying) const {
+  // Per the spec, addition of shadow lists is defined as concatenation.
+  // https://drafts.csswg.org/web-animations/#combining-shadow-lists
+  const InterpolableList& underlying_list =
+      To<InterpolableList>(*underlying.interpolable_value);
+  auto composited_list = std::make_unique<InterpolableList>(
+      underlying_list.length() + interpolable_list->length());
+  for (wtf_size_t i = 0; i < composited_list->length(); i++) {
+    if (i < underlying_list.length()) {
+      composited_list->Set(i, underlying_list.Get(i)->Clone());
+    } else {
+      composited_list->Set(
+          i, interpolable_list->Get(i - underlying_list.length())->Clone());
+    }
+  }
+  return InterpolationValue(std::move(composited_list),
+                            underlying.non_interpolable_value);
+}
+
+InterpolationValue
+CSSShadowListInterpolationType::PerformAccumulativeComposition(
+    std::unique_ptr<InterpolableList> interpolable_list,
+    const InterpolationValue& underlying) const {
+  // Per the spec, accumulation of shadow lists operates on pairwise addition of
+  // the underlying components.
+  // https://drafts.csswg.org/web-animations/#combining-shadow-lists
+  const InterpolableList& underlying_list =
+      To<InterpolableList>(*underlying.interpolable_value);
+  wtf_size_t length = interpolable_list->length();
+  wtf_size_t underlying_length = underlying_list.length();
+  // If any of the shadow style(inset or normal) value don't match, fallback to
+  // replace behavior.
+  for (wtf_size_t i = 0; i < underlying_length && i < length; i++) {
+    if (To<InterpolableShadow>(underlying_list.Get(i))->GetShadowStyle() !=
+        To<InterpolableShadow>(interpolable_list->Get(i))->GetShadowStyle()) {
+      return InterpolationValue(std::move(interpolable_list));
+    }
+  }
+
+  // Otherwise, arithmetically combine the matching prefix of the lists then
+  // concatenate the remainder of the longer one.
+  wtf_size_t max_length = std::max(length, underlying_length);
+  auto composited_list = std::make_unique<InterpolableList>(max_length);
+  for (wtf_size_t i = 0; i < max_length; i++) {
+    if (i < underlying_length) {
+      composited_list->Set(i, underlying_list.Get(i)->Clone());
+      if (i < length)
+        composited_list->GetMutable(i)->Add(*interpolable_list->Get(i));
+    } else {
+      composited_list->Set(i, interpolable_list->Get(i)->Clone());
+    }
+  }
+  return InterpolationValue(std::move(composited_list),
+                            underlying.non_interpolable_value);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.h b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.h
index 5521157..c1254e99 100644
--- a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.h
+++ b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.h
@@ -42,6 +42,17 @@
   PairwiseInterpolationValue MaybeMergeSingles(
       InterpolationValue&& start,
       InterpolationValue&& end) const final;
+  InterpolationValue PreInterpolationCompositeIfNeeded(
+      InterpolationValue value,
+      const InterpolationValue& underlying,
+      EffectModel::CompositeOperation,
+      ConversionCheckers&) const final;
+  InterpolationValue PerformAdditiveComposition(
+      std::unique_ptr<InterpolableList> interpolable_list,
+      const InterpolationValue& underlying) const;
+  InterpolationValue PerformAccumulativeComposition(
+      std::unique_ptr<InterpolableList> interpolable_list,
+      const InterpolationValue& underlying) const;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/animation/interpolable_shadow.h b/third_party/blink/renderer/core/animation/interpolable_shadow.h
index bdc200f..ddbd104 100644
--- a/third_party/blink/renderer/core/animation/interpolable_shadow.h
+++ b/third_party/blink/renderer/core/animation/interpolable_shadow.h
@@ -50,7 +50,7 @@
                         double underlying_fraction,
                         const InterpolableValue&,
                         const NonInterpolableValue*);
-
+  ShadowStyle GetShadowStyle() const { return shadow_style_; }
   // Convert this InterpolableShadow back into a ShadowData class, usually to be
   // applied to the style after interpolating it.
   ShadowData CreateShadowData(const StyleResolverState&) const;
diff --git a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
index afbb332..93beed8 100644
--- a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
+++ b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
@@ -169,17 +169,20 @@
       ToNonInterpolableList(*start.non_interpolable_value);
   const NonInterpolableList& end_non_interpolable_list =
       ToNonInterpolableList(*end.non_interpolable_value);
-
+  const wtf_size_t start_non_interpolable_length =
+      ToNonInterpolableList(*start.non_interpolable_value).length();
+  const wtf_size_t end_non_interpolable_length =
+      ToNonInterpolableList(*end.non_interpolable_value).length();
   for (wtf_size_t i = 0; i < final_length; i++) {
     if (length_matching_strategy ==
             LengthMatchingStrategy::kLowestCommonMultiple ||
         (i < start_length && i < end_length)) {
       InterpolationValue start_merge(
           start_interpolable_list.Get(i % start_length)->Clone(),
-          start_non_interpolable_list.Get(i % start_length));
+          start_non_interpolable_list.Get(i % start_non_interpolable_length));
       InterpolationValue end_merge(
           end_interpolable_list.Get(i % end_length)->Clone(),
-          end_non_interpolable_list.Get(i % end_length));
+          end_non_interpolable_list.Get(i % end_non_interpolable_length));
       PairwiseInterpolationValue result = merge_single_item_conversions.Run(
           std::move(start_merge), std::move(end_merge));
       if (!result)
@@ -198,18 +201,22 @@
             i, start_interpolable_list.Get(i)->Clone());
         result_end_interpolable_list->Set(
             i, start_interpolable_list.Get(i)->CloneAndZero());
-        result_non_interpolable_values[i] = start_non_interpolable_list.Get(i);
+        result_non_interpolable_values[i] =
+            (i < start_non_interpolable_length)
+                ? start_non_interpolable_list.Get(i)
+                : nullptr;
       } else {
         DCHECK_LT(i, end_length);
         result_start_interpolable_list->Set(
             i, end_interpolable_list.Get(i)->CloneAndZero());
         result_end_interpolable_list->Set(
             i, end_interpolable_list.Get(i)->Clone());
-        result_non_interpolable_values[i] = end_non_interpolable_list.Get(i);
+        result_non_interpolable_values[i] =
+            (i < end_non_interpolable_length) ? end_non_interpolable_list.Get(i)
+                                              : nullptr;
       }
     }
   }
-
   return PairwiseInterpolationValue(
       std::move(result_start_interpolable_list),
       std::move(result_end_interpolable_list),
diff --git a/third_party/blink/renderer/core/css/properties/css_property.h b/third_party/blink/renderer/core/css/properties/css_property.h
index e1248d5..33eec78 100644
--- a/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/third_party/blink/renderer/core/css/properties/css_property.h
@@ -115,6 +115,9 @@
     // 'background-color' would have had without any user or author
     // declarations.
     kUA = 1 << 10,
+    // Animation properties have this flag set. (I.e. longhands of the
+    // 'animation' and 'transition' shorthands).
+    kAnimation = 1 << 11,
   };
 
   constexpr CSSProperty(CSSPropertyID property_id,
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 2ae6f19..ae5dfe4 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -175,16 +175,6 @@
   mask_ = 0;
 }
 
-void StyleCascade::RemoveAnimationPriority() {
-  using AnimPrio = CSSPropertyPriorityData<kAnimationPropertyPriority>;
-  int first = static_cast<int>(AnimPrio::First());
-  int last = static_cast<int>(AnimPrio::Last());
-  for (int i = first; i <= last; ++i) {
-    CSSPropertyName name(convertToCSSPropertyID(i));
-    cascade_.erase(name);
-  }
-}
-
 const CSSValue* StyleCascade::Resolve(const CSSPropertyName& name,
                                       const CSSValue& value,
                                       Resolver& resolver) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.h b/third_party/blink/renderer/core/css/resolver/style_cascade.h
index 032ad35f..963980b 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.h
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.h
@@ -241,13 +241,6 @@
     CSSProperty::Flags flags_ = 0;
   };
 
-  // Removes all kAnimationPropertyPriority properties from the cascade,
-  // without applying the properties. This is used when pre-emptively copying
-  // the cascade in case there are animations.
-  //
-  // TODO(crbug.com/985010): Improve with non-destructive Apply.
-  void RemoveAnimationPriority();
-
   // Resolver is an object passed on a stack during Apply. Its most important
   // job is to detect cycles during Apply (in general, keep track of which
   // properties we're currently applying).
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 880c118c..52edde4 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2175,7 +2175,6 @@
   //
   // TODO(crbug.com/985010): Avoid this copy with non-destructive Apply.
   StyleCascade cascade_copy(cascade);
-  cascade_copy.RemoveAnimationPriority();
 
   if (!cache_success.IsFullCacheHit())
     cascade.Apply();
@@ -2189,6 +2188,7 @@
       CascadeAnimations(state, cascade_copy);
       CascadeTransitions(state, cascade_copy);
       StyleAnimator animator(state, cascade_copy);
+      cascade_copy.Exclude(CSSProperty::kAnimation, true);
       cascade_copy.Apply(animator);
     }
   }
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index cc63c0f..c0f12a8 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -45,7 +45,7 @@
 
 // Helper function to convert a display locking state to a string. Used in
 // traces.
-std::string StateToString(DisplayLockContext::State state) {
+const char* StateToString(DisplayLockContext::State state) {
   switch (state) {
     case DisplayLockContext::kLocked:
       return "kLocked";
@@ -952,13 +952,13 @@
     return *this;
 
   if (state_ == kUnlocked) {
-    TRACE_EVENT_ASYNC_BEGIN0(
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
         TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
-        "LockedDisplayLock", this);
-  } else if (new_state == kUnlocked) {
-    TRACE_EVENT_ASYNC_END0(
+        "LockedDisplayLock", TRACE_ID_LOCAL(this));
+  } else {
+    TRACE_EVENT_NESTABLE_ASYNC_END0(
         TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
-        "LockedDisplayLock", this);
+        StateToString(state_), TRACE_ID_LOCAL(this));
   }
 
   bool was_activatable =
@@ -966,10 +966,15 @@
   bool was_locked = context_->IsLocked();
 
   state_ = new_state;
-  if (state_ != kUnlocked) {
-    TRACE_EVENT_ASYNC_STEP_INTO0(
+
+  if (state_ == kUnlocked) {
+    TRACE_EVENT_NESTABLE_ASYNC_END0(
         TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
-        "LockedDisplayLock", this, StateToString(state_));
+        "LockedDisplayLock", TRACE_ID_LOCAL(this));
+  } else {
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+        TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
+        StateToString(state_), TRACE_ID_LOCAL(this));
   }
 
   if (!context_->document_)
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc
index 3fae6f3..64ec687 100644
--- a/third_party/blink/renderer/core/dom/container_node.cc
+++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -1008,13 +1008,15 @@
   GetDocument().IncDOMTreeVersion();
   GetDocument().NotifyChangeChildren(*this);
   InvalidateNodeListCachesInAncestors(nullptr, nullptr, &change);
-
   if (change.IsChildRemoval() || change.type == kAllChildrenRemoved) {
     GetDocument().GetStyleEngine().ChildrenRemoved(*this);
     return;
   }
   if (!change.IsChildInsertion())
     return;
+  Node* inserted_node = change.sibling_changed;
+  if (inserted_node->IsContainerNode() || inserted_node->IsTextNode())
+    inserted_node->ClearFlatTreeNodeDataIfHostChanged(*this);
   if (!InActiveDocument())
     return;
   if (IsElementNode() && !GetComputedStyle()) {
@@ -1025,11 +1027,8 @@
     // the ComputedStyle goes from null to non-null.
     return;
   }
-  Node* inserted_node = change.sibling_changed;
-  if (inserted_node->IsContainerNode() || inserted_node->IsTextNode()) {
-    inserted_node->ClearFlatTreeNodeDataIfHostChanged(*this);
+  if (inserted_node->IsContainerNode() || inserted_node->IsTextNode())
     inserted_node->SetStyleChangeOnInsertion();
-  }
 }
 
 void ContainerNode::CloneChildNodesFrom(const ContainerNode& node) {
diff --git a/third_party/blink/renderer/core/events/web_input_event_conversion.cc b/third_party/blink/renderer/core/events/web_input_event_conversion.cc
index fcf3fc6b..716617985 100644
--- a/third_party/blink/renderer/core/events/web_input_event_conversion.cc
+++ b/third_party/blink/renderer/core/events/web_input_event_conversion.cc
@@ -120,8 +120,8 @@
 WebPointerEvent TransformWebPointerEvent(float frame_scale,
                                          gfx::Vector2dF frame_translate,
                                          const WebPointerEvent& event) {
-  // frameScale is default initialized to 1.
-  DCHECK_EQ(1, event.FrameScale());
+  // frameScale is default initialized in debug builds to be 0.
+  DCHECK_EQ(0, event.FrameScale());
   DCHECK_EQ(0, event.FrameTranslate().x());
   DCHECK_EQ(0, event.FrameTranslate().y());
   WebPointerEvent result = event;
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 35d7e03..e54974fd 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -364,7 +364,8 @@
         html_element->IsPluginElement()) {
       mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
       main_frame.Client()->SetMouseCapture(true);
-      TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
+                                        TRACE_ID_LOCAL(this));
     }
   }
 
@@ -1873,7 +1874,8 @@
 }
 
 void WebViewImpl::MouseCaptureLost() {
-  TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
+                                  TRACE_ID_LOCAL(this));
   mouse_capture_element_ = nullptr;
   if (AsView().page->DeprecatedLocalMainFrame())
     AsView().page->DeprecatedLocalMainFrame()->Client()->SetMouseCapture(false);
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index e65c822..272aa5f 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -547,7 +547,8 @@
 }
 
 void WebFrameWidgetImpl::MouseCaptureLost() {
-  TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
+                                  TRACE_ID_LOCAL(this));
   mouse_capture_element_ = nullptr;
 }
 
@@ -696,7 +697,8 @@
         hit_node->GetLayoutObject()->IsEmbeddedObject() && html_element &&
         html_element->IsPluginElement()) {
       mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
-      TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
+                                        TRACE_ID_LOCAL(this));
     }
   }
 
diff --git a/third_party/blink/renderer/core/html/html_meter_element.cc b/third_party/blink/renderer/core/html/html_meter_element.cc
index 863c800..ada15e6 100644
--- a/third_party/blink/renderer/core/html/html_meter_element.cc
+++ b/third_party/blink/renderer/core/html/html_meter_element.cc
@@ -184,15 +184,7 @@
 
   value_ = MakeGarbageCollected<HTMLDivElement>(GetDocument());
   UpdateValueAppearance(0);
-
-  if (features::IsFormControlsRefreshEnabled()) {
-    auto* clip = MakeGarbageCollected<HTMLDivElement>(GetDocument());
-    clip->SetShadowPseudoId(AtomicString("-internal-meter-clip"));
-    bar->AppendChild(clip);
-    clip->AppendChild(value_);
-  } else {
-    bar->AppendChild(value_);
-  }
+  bar->AppendChild(value_);
 
   inner->AppendChild(bar);
 
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css
index eeace5a..cc4d8c7 100644
--- a/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -83,26 +83,21 @@
   color: #c5c5c5;
 }
 
-meter::-webkit-meter-inner-element::before,
-meter::-webkit-meter-inner-element::after {
-  display: block;
-  content: "";
-  height: 25%;
+meter::-webkit-meter-inner-element:-internal-shadow-host-has-appearance {
+  display: grid;
+  grid-template-rows: 1fr [line1] 2fr [line2] 1fr;
 }
 
 meter::-webkit-meter-bar {
   background: #efefef;
   border-width: thin;
-  height: 50%;
+  grid-row-start: line1;
+  grid-row-end: line2;
   border-style: solid;
   border-color: rgba(118, 118, 118, 0.3);
   border-radius: 20px;
   box-sizing: border-box;
-}
-
-meter::-internal-meter-clip {
-  clip-path: inset(0px round 20px);
-  height: 100%;
+  overflow: hidden;
 }
 
 meter::-webkit-meter-optimum-value {
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
index b17bb57..5e2d59c0 100644
--- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
@@ -374,8 +374,9 @@
   virtual_time_base_ticks_ =
       web_local_frame_->View()->Scheduler()->EnableVirtualTime();
   if (new_policy.virtual_time_budget_ms) {
-    TRACE_EVENT_ASYNC_BEGIN1("renderer.scheduler", "VirtualTimeBudget", this,
-                             "budget", *new_policy.virtual_time_budget_ms);
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("renderer.scheduler", "VirtualTimeBudget",
+                                      TRACE_ID_LOCAL(this), "budget",
+                                      *new_policy.virtual_time_budget_ms);
     base::TimeDelta budget_amount =
         base::TimeDelta::FromMillisecondsD(*new_policy.virtual_time_budget_ms);
     web_local_frame_->View()->Scheduler()->GrantVirtualTimeBudget(
@@ -423,7 +424,8 @@
 }
 
 void InspectorEmulationAgent::VirtualTimeBudgetExpired() {
-  TRACE_EVENT_ASYNC_END0("renderer.scheduler", "VirtualTimeBudget", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler", "VirtualTimeBudget",
+                                  TRACE_ID_LOCAL(this));
   WebView* view = web_local_frame_->View();
   if (!view)
     return;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index ea16af4..ecd28a2 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -167,13 +167,11 @@
  public:
   InspectorFileReaderLoaderClient(
       scoped_refptr<BlobDataHandle> blob,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       base::OnceCallback<void(scoped_refptr<SharedBuffer>)> callback)
       : blob_(std::move(blob)), callback_(std::move(callback)) {
-    // TODO(hajimehoshi): Use a per-ExecutionContext task runner of
-    // TaskType::kFileReading
     loader_ = std::make_unique<FileReaderLoader>(
-        FileReaderLoader::kReadByClient, this,
-        ThreadScheduler::Current()->DeprecatedDefaultTaskRunner());
+        FileReaderLoader::kReadByClient, this, std::move(task_runner));
   }
 
   ~InspectorFileReaderLoaderClient() override = default;
@@ -233,9 +231,12 @@
 class InspectorPostBodyParser
     : public WTF::RefCounted<InspectorPostBodyParser> {
  public:
-  explicit InspectorPostBodyParser(
-      std::unique_ptr<GetRequestPostDataCallback> callback)
-      : callback_(std::move(callback)), error_(false) {}
+  InspectorPostBodyParser(
+      std::unique_ptr<GetRequestPostDataCallback> callback,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+      : callback_(std::move(callback)),
+        task_runner_(std::move(task_runner)),
+        error_(false) {}
 
   void Parse(EncodedFormData* request_body) {
     if (!request_body || request_body->IsEmpty())
@@ -287,13 +288,14 @@
     if (!blob_handle)
       return;
     auto* reader = new InspectorFileReaderLoaderClient(
-        blob_handle,
+        blob_handle, task_runner_,
         WTF::Bind(&InspectorPostBodyParser::BlobReadCallback,
                   WTF::RetainedRef(this), WTF::Unretained(destination)));
     reader->Start();
   }
 
   std::unique_ptr<GetRequestPostDataCallback> callback_;
+  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   bool error_;
   Vector<String> parts_;
   DISALLOW_COPY_AND_ASSIGN(InspectorPostBodyParser);
@@ -1414,8 +1416,13 @@
   NetworkResourcesData::ResourceData const* resource_data =
       resources_data_->Data(request_id);
   BlobDataHandle* blob = resource_data->DownloadedFileBlob();
+  ExecutionContext* context = GetTargetExecutionContext();
+  if (!context) {
+    callback->sendFailure(Response::InternalError());
+    return;
+  }
   InspectorFileReaderLoaderClient* client = new InspectorFileReaderLoaderClient(
-      blob,
+      blob, context->GetTaskRunner(TaskType::kFileReading),
       WTF::Bind(ResponseBodyFileReaderLoaderDone, resource_data->MimeType(),
                 resource_data->TextEncodingName(),
                 WTF::Passed(std::move(callback))));
@@ -1743,11 +1750,23 @@
         Response::Error("No post data available for the request"));
     return;
   }
-
+  ExecutionContext* context = GetTargetExecutionContext();
+  if (!context) {
+    callback->sendFailure(Response::InternalError());
+    return;
+  }
   scoped_refptr<InspectorPostBodyParser> parser =
-      base::MakeRefCounted<InspectorPostBodyParser>(std::move(callback));
+      base::MakeRefCounted<InspectorPostBodyParser>(
+          std::move(callback), context->GetTaskRunner(TaskType::kFileReading));
   // TODO(crbug.com/810554): Extend protocol to fetch body parts separately
   parser->Parse(post_data.get());
 }
 
+ExecutionContext* InspectorNetworkAgent::GetTargetExecutionContext() const {
+  if (worker_global_scope_)
+    return worker_global_scope_;
+  DCHECK(inspected_frames_);
+  return inspected_frames_->Root()->GetDocument();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
index dba8a6d..4d14b2f 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -257,6 +257,7 @@
   bool CanGetResponseBodyBlob(const String& request_id);
   void GetResponseBodyBlob(const String& request_id,
                            std::unique_ptr<GetResponseBodyCallback>);
+  ExecutionContext* GetTargetExecutionContext() const;
 
   static std::unique_ptr<protocol::Network::Initiator> BuildInitiatorObject(
       Document*,
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 228e4a34..1b1fa8d 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -1532,6 +1532,9 @@
       // We don't really know whether the containing block of this child did
       // change or is going to change size. However, this is our only
       // opportunity to make sure that it gets its min/max widths calculated.
+      // This is also an important hook for flow threads; if the container of a
+      // flow thread needs its preferred logical widths recalculated, so does
+      // the flow thread, potentially.
       child->SetPreferredLogicalWidthsDirty();
     }
 
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 e80df2a..f2731e8 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -77,7 +77,8 @@
 
 struct SameSizeAsLayoutBlockFlow : public LayoutBlock {
   LineBoxList line_boxes;
-  void* pointers[2];
+  void* pointers[1];
+  Persistent<void*> persistent[1];
 };
 
 static_assert(sizeof(LayoutBlockFlow) == sizeof(SameSizeAsLayoutBlockFlow),
@@ -2241,7 +2242,7 @@
     if (pos == LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this) &&
         neg == LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this))
       return;
-    rare_data_ = std::make_unique<LayoutBlockFlowRareData>(this);
+    rare_data_ = MakeGarbageCollected<LayoutBlockFlowRareData>(this);
   }
   rare_data_->margins_.SetPositiveMarginBefore(pos);
   rare_data_->margins_.SetNegativeMarginBefore(neg);
@@ -2252,7 +2253,7 @@
     if (pos == LayoutBlockFlowRareData::PositiveMarginAfterDefault(this) &&
         neg == LayoutBlockFlowRareData::NegativeMarginAfterDefault(this))
       return;
-    rare_data_ = std::make_unique<LayoutBlockFlowRareData>(this);
+    rare_data_ = MakeGarbageCollected<LayoutBlockFlowRareData>(this);
   }
   rare_data_->margins_.SetPositiveMarginAfter(pos);
   rare_data_->margins_.SetNegativeMarginAfter(neg);
@@ -4193,7 +4194,7 @@
   if (!rare_data_) {
     if (!strut)
       return;
-    rare_data_ = std::make_unique<LayoutBlockFlowRareData>(this);
+    rare_data_ = MakeGarbageCollected<LayoutBlockFlowRareData>(this);
   }
   rare_data_->pagination_strut_propagated_from_child_ = strut;
 }
@@ -4202,7 +4203,7 @@
   if (!rare_data_) {
     if (!block_offset)
       return;
-    rare_data_ = std::make_unique<LayoutBlockFlowRareData>(this);
+    rare_data_ = MakeGarbageCollected<LayoutBlockFlowRareData>(this);
   }
   rare_data_->first_forced_break_offset_ = block_offset;
 }
@@ -4317,7 +4318,7 @@
   if (rare_data_)
     return *rare_data_;
 
-  rare_data_ = std::make_unique<LayoutBlockFlowRareData>(this);
+  rare_data_ = MakeGarbageCollected<LayoutBlockFlowRareData>(this);
   return *rare_data_;
 }
 
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 b0666ca..aca22f7 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -733,9 +733,8 @@
   MarginValues MarginValuesForChild(LayoutBox& child) const;
 
   // Allocated only when some of these fields have non-default values
-  struct LayoutBlockFlowRareData {
-    USING_FAST_MALLOC(LayoutBlockFlowRareData);
-
+  struct LayoutBlockFlowRareData final
+      : public GarbageCollected<LayoutBlockFlowRareData> {
    public:
     explicit LayoutBlockFlowRareData(const LayoutBlockFlow* block);
     ~LayoutBlockFlowRareData();
@@ -755,6 +754,8 @@
       return (-block->MarginAfter()).ClampNegativeToZero();
     }
 
+    void Trace(Visitor*) {}
+
     MarginValues margins_;
     LayoutUnit pagination_strut_propagated_from_child_;
 
@@ -911,7 +912,7 @@
   bool CheckIfIsSelfCollapsingBlock() const;
 
  protected:
-  std::unique_ptr<LayoutBlockFlowRareData> rare_data_;
+  Persistent<LayoutBlockFlowRareData> rare_data_;
   std::unique_ptr<FloatingObjects> floating_objects_;
 
   friend class MarginInfo;
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.h b/third_party/blink/renderer/core/layout/layout_flow_thread.h
index 51130666c..d43f6eb 100644
--- a/third_party/blink/renderer/core/layout/layout_flow_thread.h
+++ b/third_party/blink/renderer/core/layout/layout_flow_thread.h
@@ -105,6 +105,8 @@
   // can easily avoid drawing the children directly.
   PaintLayerType LayerTypeRequired() const final { return kNormalPaintLayer; }
 
+  bool NeedsPreferredWidthsRecalculation() const final { return true; }
+
   virtual void FlowThreadDescendantWasInserted(LayoutObject*) {}
   virtual void FlowThreadDescendantWillBeRemoved(LayoutObject*) {}
   virtual void FlowThreadDescendantStyleWillChange(
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index 50bfca90..a8a8444 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -55,6 +56,15 @@
 
 namespace {
 
+// TODO(layout-dev): Once we generate fragment for all inline element, we should
+// use |LayoutObject::EnclosingBlockFlowFragment()|.
+const NGPhysicalBoxFragment* ContainingBlockFlowFragmentOf(
+    const LayoutInline& node) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return nullptr;
+  return node.ContainingBlockFlowFragment();
+}
+
 // TODO(xiaochengh): Deduplicate with a similar function in ng_paint_fragment.cc
 // ::before, ::after and ::first-letter can be hit test targets.
 bool CanBeHitTestTargetPseudoNodeStyle(const ComputedStyle& style) {
@@ -777,10 +787,12 @@
 void LayoutInline::CollectLineBoxRects(
     const PhysicalRectCollector& yield) const {
   if (IsInLayoutNGInlineFormattingContext()) {
-    NGInlineCursor cursor;
-    cursor.MoveTo(*this);
-    for (; cursor; cursor.MoveToNextForSameLayoutObject())
-      yield(cursor.CurrentRect());
+    const auto* box_fragment = ContainingBlockFlowFragmentOf(*this);
+    if (!box_fragment)
+      return;
+    for (const auto& fragment :
+         NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this))
+      yield(fragment.RectInContainerBox());
     return;
   }
   if (!AlwaysCreateLineBoxes()) {
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
index 924dd0e..d80b5b3 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
@@ -452,8 +452,7 @@
 void LayoutMultiColumnSet::ComputeIntrinsicLogicalWidths(
     LayoutUnit& min_logical_width,
     LayoutUnit& max_logical_width) const {
-  min_logical_width = flow_thread_->MinPreferredLogicalWidth();
-  max_logical_width = flow_thread_->MaxPreferredLogicalWidth();
+  max_logical_width = min_logical_width = LayoutUnit();
 }
 
 void LayoutMultiColumnSet::ComputeLogicalHeight(
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 0c5a57ad..a958137b 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1131,9 +1131,11 @@
   // next block container.
   // Atomic inlines do not have this problem as they are treated like blocks
   // in this context.
+  // There's a similar issue for flow thread objects, as they are invisible to
+  // LayoutNG.
   if (!RuntimeEnabledFeatures::LayoutNGEnabled())
     return false;
-  if (o->IsLayoutInline() || o->IsText())
+  if (o->IsLayoutInline() || o->IsText() || o->IsLayoutFlowThread())
     return true;
   return false;
 }
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 2bc227e..637d2fa 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
@@ -82,15 +82,15 @@
       // Floats are in the fragment tree, not in the fragment item list.
       DCHECK(!box.IsFloating());
 
+      // Take the fast path when we know |child| does not have child items.
       if (child.children_count <= 1) {
         // Compute |has_floating_descendants_for_paint_| to optimize tree
         // traversal in paint.
         if (!has_floating_descendants_for_paint_ && box.IsFloating())
           has_floating_descendants_for_paint_ = true;
 
-        DCHECK(child.HasBidiLevel());
         items_.push_back(std::make_unique<NGFragmentItem>(
-            box, 1, DirectionFromLevel(child.bidi_level)));
+            box, 1, child.ResolvedDirection()));
         offsets_.push_back(child.offset);
         ++child_iter;
         continue;
@@ -116,9 +116,8 @@
       wtf_size_t item_count = items_.size() - box_start_index;
 
       // Create an item for the start of the box.
-      DCHECK(child.HasBidiLevel());
       items_[box_start_index] = std::make_unique<NGFragmentItem>(
-          box, item_count, DirectionFromLevel(child.bidi_level));
+          box, item_count, child.ResolvedDirection());
       continue;
     }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index f2c2f039..5827d57c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -105,7 +105,8 @@
 NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
     const ComputedStyle& line_style,
     FontBaseline baseline_type,
-    bool line_height_quirk) {
+    bool line_height_quirk,
+    NGLineBoxFragmentBuilder::ChildList* line_box) {
   if (stack_.IsEmpty()) {
     // For the first line, push a box state for the line itself.
     stack_.resize(1);
@@ -114,7 +115,9 @@
   } else {
     // For the following lines, clear states that are not shared across lines.
     for (NGInlineBoxState& box : stack_) {
-      box.fragment_start = 0;
+      box.fragment_start = line_box->size();
+      if (&box != stack_.begin())
+        AddBoxFragmentPlaceholder(&box, line_box, baseline_type);
       if (!line_height_quirk)
         box.metrics = box.text_metrics;
       else
@@ -133,15 +136,15 @@
   DCHECK(box_data_list_.IsEmpty());
 
   // Initialize the box state for the line box.
-  NGInlineBoxState& line_box = LineBoxState();
-  if (line_box.style != &line_style) {
-    line_box.style = &line_style;
+  NGInlineBoxState& line_box_state = LineBoxState();
+  if (line_box_state.style != &line_style) {
+    line_box_state.style = &line_style;
 
     // Use a "strut" (a zero-width inline box with the element's font and
     // line height properties) as the initial metrics for the line box.
     // https://drafts.csswg.org/css2/visudet.html#strut
     if (!line_height_quirk)
-      line_box.ComputeTextMetrics(line_style, baseline_type);
+      line_box_state.ComputeTextMetrics(line_style, baseline_type);
   }
 
   return &stack_.back();
@@ -150,16 +153,27 @@
 NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
     const NGInlineItem& item,
     const NGInlineItemResult& item_result,
+    FontBaseline baseline_type,
+    NGLineBoxFragmentBuilder::ChildList* line_box) {
+  NGInlineBoxState* box =
+      OnOpenTag(item, item_result, baseline_type, *line_box);
+  AddBoxFragmentPlaceholder(box, line_box, baseline_type);
+  return box;
+}
+
+NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
+    const NGInlineItem& item,
+    const NGInlineItemResult& item_result,
+    FontBaseline baseline_type,
     const NGLineBoxFragmentBuilder::ChildList& line_box) {
   DCHECK(item.Style());
-  NGInlineBoxState* box = OnOpenTag(*item.Style(), line_box);
+  const ComputedStyle& style = *item.Style();
+  stack_.resize(stack_.size() + 1);
+  NGInlineBoxState* box = &stack_.back();
+  box->fragment_start = line_box.size();
+  box->style = &style;
   box->item = &item;
-
-  if (item.ShouldCreateBoxFragment())
-    box->SetNeedsBoxFragment();
-
-  // Compute box properties regardless of needs_box_fragment since close tag may
-  // also set needs_box_fragment.
+  box->needs_box_fragment = item.ShouldCreateBoxFragment();
   box->has_start_edge = item_result.has_edge;
   box->margin_inline_start = item_result.margins.inline_start;
   box->margin_inline_end = item_result.margins.inline_end;
@@ -168,16 +182,6 @@
   return box;
 }
 
-NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
-    const ComputedStyle& style,
-    const NGLineBoxFragmentBuilder::ChildList& line_box) {
-  stack_.resize(stack_.size() + 1);
-  NGInlineBoxState* box = &stack_.back();
-  box->fragment_start = line_box.size();
-  box->style = &style;
-  return box;
-}
-
 NGInlineBoxState* NGInlineLayoutStateStack::OnCloseTag(
     NGLineBoxFragmentBuilder::ChildList* line_box,
     NGInlineBoxState* box,
@@ -209,8 +213,8 @@
   // Copy the final offset to |box_data_list_|.
   for (BoxData& box_data : box_data_list_) {
     const NGLineBoxFragmentBuilder::Child& placeholder =
-        (*line_box)[box_data.fragment_end];
-    DCHECK(!placeholder.HasFragment());
+        (*line_box)[box_data.fragment_start];
+    DCHECK(placeholder.IsPlaceholder());
     box_data.offset = placeholder.offset;
   }
 }
@@ -220,7 +224,7 @@
     NGLineBoxFragmentBuilder::ChildList* line_box,
     FontBaseline baseline_type) {
   if (box->needs_box_fragment)
-    AddBoxFragmentPlaceholder(box, line_box, baseline_type);
+    AddBoxData(box, line_box);
 
   PositionPending position_pending =
       ApplyBaselineShift(box, line_box, baseline_type);
@@ -251,12 +255,11 @@
     NGInlineBoxState* box,
     NGLineBoxFragmentBuilder::ChildList* line_box,
     FontBaseline baseline_type) {
-  DCHECK(box->needs_box_fragment);
   DCHECK(box->style);
   const ComputedStyle& style = *box->style;
 
-  LogicalOffset offset;
-  LogicalSize size;
+  LayoutUnit block_offset;
+  LayoutUnit block_size;
   if (!is_empty_line_) {
     // The inline box should have the height of the font metrics without the
     // line-height property. Compute from style because |box->metrics| includes
@@ -265,16 +268,29 @@
 
     // Extend the block direction of the box by borders and paddings. Inline
     // direction is already included into positions in NGLineBreaker.
-    offset.block_offset =
+    block_offset =
         -metrics.ascent - (box->borders.line_over + box->padding.line_over);
-    size.block_size = metrics.LineHeight() + box->borders.BlockSum() +
-                      box->padding.BlockSum();
+    block_size = metrics.LineHeight() + box->borders.BlockSum() +
+                 box->padding.BlockSum();
   }
+  line_box->AddChild(block_offset, block_size);
+  DCHECK((*line_box)[line_box->size() - 1].IsPlaceholder());
+}
 
-  unsigned fragment_end = line_box->size();
+// Add a |BoxData|, for each close-tag that needs a box fragment.
+void NGInlineLayoutStateStack::AddBoxData(
+    NGInlineBoxState* box,
+    NGLineBoxFragmentBuilder::ChildList* line_box) {
+  DCHECK(box->needs_box_fragment);
+  DCHECK(box->style);
+  const ComputedStyle& style = *box->style;
+  NGLineBoxFragmentBuilder::Child& placeholder =
+      (*line_box)[box->fragment_start];
+  DCHECK(placeholder.IsPlaceholder());
+  const unsigned fragment_end = line_box->size();
   DCHECK(box->item);
   BoxData& box_data = box_data_list_.emplace_back(
-      box->fragment_start, fragment_end, box->item, size);
+      box->fragment_start, fragment_end, box->item, placeholder.size);
   box_data.padding = box->padding;
   if (box->has_start_edge) {
     box_data.has_line_left_edge = true;
@@ -297,31 +313,23 @@
               box_data.margin_border_padding_line_right);
   }
 
-  if (fragment_end > box->fragment_start) {
-    // The start is marked only in BoxData, while end is marked
-    // in both BoxData and the list itself.
-    // With a list of 4 text fragments:
-    // |  0  |  1  |  2  |  3  |
-    // |text0|text1|text2|text3|
-    // By adding a BoxData(2,4) (end is exclusive), it becomes:
-    // |  0  |  1  |  2  |  3  |  4  |
-    // |text0|text1|text2|text3|null |
-    // The "null" is added to the list to compute baseline shift of the box
-    // separately from text fragments.
-    line_box->AddChild(offset);
-  } else {
-    // Do not defer creating a box fragment if this is an empty inline box.
-    // An empty box fragment is still flat that we do not have to defer.
-    // Also, placeholders cannot be reordred if empty.
-    offset.inline_offset += box_data.margin_line_left;
-    LayoutUnit advance = box_data.margin_border_padding_line_left +
-                         box_data.margin_border_padding_line_right;
-    box_data.size.inline_size =
-        advance - box_data.margin_line_left - box_data.margin_line_right;
-    line_box->AddChild(box_data.CreateBoxFragment(line_box), offset, advance,
-                       /* bidi_level */ 0);
-    box_data_list_.pop_back();
-  }
+  DCHECK((*line_box)[box->fragment_start].IsPlaceholder());
+  DCHECK_GT(fragment_end, box->fragment_start);
+  if (fragment_end > box->fragment_start + 1)
+    return;
+
+  // Do not defer creating a box fragment if this is an empty inline box.
+  // An empty box fragment is still flat that we do not have to defer.
+  // Also, placeholders cannot be reordred if empty.
+  placeholder.offset.inline_offset += box_data.margin_line_left;
+  LayoutUnit advance = box_data.margin_border_padding_line_left +
+                       box_data.margin_border_padding_line_right;
+  box_data.size.inline_size =
+      advance - box_data.margin_line_left - box_data.margin_line_right;
+  placeholder.layout_result = box_data.CreateBoxFragment(line_box);
+  placeholder.inline_size = advance;
+  DCHECK(!placeholder.children_count);
+  box_data_list_.pop_back();
 }
 
 void NGInlineLayoutStateStack::ChildInserted(unsigned index) {
@@ -348,6 +356,7 @@
   unsigned box_data_index = 0;
   for (const BoxData& box_data : box_data_list_) {
     box_data_index++;
+    DCHECK((*line_box)[box_data.fragment_start].IsPlaceholder());
     for (unsigned i = box_data.fragment_start; i < box_data.fragment_end; i++) {
       NGLineBoxFragmentBuilder::Child& child = (*line_box)[i];
       if (!child.box_data_index)
@@ -358,10 +367,11 @@
   // When boxes are nested, placeholders have indexes to which box it should be
   // added. Copy them to BoxData.
   for (BoxData& box_data : box_data_list_) {
-    const NGLineBoxFragmentBuilder::Child& placeholder =
-        (*line_box)[box_data.fragment_end];
-    DCHECK(!placeholder.HasFragment());
-    box_data.parent_box_data_index = placeholder.box_data_index;
+    if (!box_data.fragment_start)
+      continue;
+    const NGLineBoxFragmentBuilder::Child& parent =
+        (*line_box)[box_data.fragment_start - 1];
+    box_data.parent_box_data_index = parent.box_data_index;
   }
 }
 
@@ -569,24 +579,20 @@
     unsigned end = box_data.fragment_end;
     DCHECK_GT(end, start);
     NGLineBoxFragmentBuilder::Child* child = &(*line_box)[start];
-
     scoped_refptr<const NGLayoutResult> box_fragment =
         box_data.CreateBoxFragment(line_box);
-    if (!child->HasFragment()) {
+    if (child->IsPlaceholder()) {
       child->layout_result = std::move(box_fragment);
       child->offset = box_data.offset;
       child->children_count = end - start;
-    } else {
-      // In most cases, |start_child| is moved to the children of the box, and
-      // is empty. It's not empty when it's out-of-flow. Insert in such case.
-      // TODO(kojii): With |NGFragmentItem|, all cases hit this code. Consider
-      // creating an empty item beforehand to avoid inserting.
-      line_box->InsertChild(start, std::move(box_fragment), box_data.offset,
-                            LayoutUnit(), 0);
-      ChildInserted(start + 1);
-      child = &(*line_box)[start];
-      child->children_count = end - start + 1;
+      continue;
     }
+
+    // |AddBoxFragmentPlaceholder| adds a placeholder at |fragment_start|, but
+    // bidi reordering may move it. Insert in such case.
+    line_box->InsertChild(start, std::move(box_fragment), box_data.offset,
+                          end - start + 1);
+    ChildInserted(start + 1);
   }
 
   box_data_list_.clear();
@@ -826,8 +832,10 @@
       continue;
 
     // |block_offset| is the top position when the baseline is at 0.
-    LayoutUnit box_ascent =
-        -line_box[box_data.fragment_end].offset.block_offset;
+    const NGLineBoxFragmentBuilder::Child& placeholder =
+        line_box[box_data.fragment_start];
+    DCHECK(placeholder.IsPlaceholder());
+    LayoutUnit box_ascent = -placeholder.offset.block_offset;
     NGLineHeightMetrics box_metrics(box_ascent,
                                     box_data.size.block_size - box_ascent);
     // The top/bottom of inline boxes should not include their paddings.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index 066225e8..c4521acc 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -116,14 +116,22 @@
 
   // Initialize the box state stack for a new line.
   // @return The initial box state for the line.
-  NGInlineBoxState* OnBeginPlaceItems(const ComputedStyle&, FontBaseline, bool);
+  NGInlineBoxState* OnBeginPlaceItems(
+      const ComputedStyle&,
+      FontBaseline,
+      bool line_height_quirk,
+      NGLineBoxFragmentBuilder::ChildList* line_box);
 
   // Push a box state stack.
   NGInlineBoxState* OnOpenTag(const NGInlineItem&,
                               const NGInlineItemResult&,
+                              FontBaseline baseline_type,
                               const NGLineBoxFragmentBuilder::ChildList&);
-  NGInlineBoxState* OnOpenTag(const ComputedStyle&,
-                              const NGLineBoxFragmentBuilder::ChildList&);
+  // This variation adds a box placeholder to |line_box|.
+  NGInlineBoxState* OnOpenTag(const NGInlineItem&,
+                              const NGInlineItemResult&,
+                              FontBaseline baseline_type,
+                              NGLineBoxFragmentBuilder::ChildList* line_box);
 
   // Pop a box state stack.
   NGInlineBoxState* OnCloseTag(NGLineBoxFragmentBuilder::ChildList*,
@@ -182,6 +190,7 @@
   void AddBoxFragmentPlaceholder(NGInlineBoxState*,
                                  NGLineBoxFragmentBuilder::ChildList*,
                                  FontBaseline);
+  void AddBoxData(NGInlineBoxState*, NGLineBoxFragmentBuilder::ChildList*);
 
   enum PositionPending { kPositionNotPending, kPositionPending };
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
index 863a43a..d9aa540 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
@@ -164,6 +164,27 @@
 }  // namespace
 
 // static
+Vector<Result> NGInlineFragmentTraversal::SelfFragmentsOf(
+    const NGPhysicalContainerFragment& container,
+    const LayoutObject* layout_object) {
+  if (const LayoutInline* layout_inline = ToLayoutInlineOrNull(layout_object)) {
+    // TODO(crbug.com/874361): Stop partial culling of inline boxes, so that we
+    // can simply check existence of paint fragments below.
+    if (!layout_inline->HasSelfPaintingLayer()) {
+      return LayoutInlineCollector(ToLayoutInline(*layout_object))
+          .CollectFrom(container);
+    }
+  }
+  Vector<Result> result;
+  for (const NGPaintFragment* fragment :
+       NGPaintFragment::InlineFragmentsFor(layout_object)) {
+    result.push_back(Result{&fragment->PhysicalFragment(),
+                            fragment->InlineOffsetToContainerBox()});
+  }
+  return result;
+}
+
+// static
 Vector<Result> NGInlineFragmentTraversal::DescendantsOf(
     const NGPhysicalContainerFragment& container) {
   return DescendantCollector().CollectFrom(container);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
index 195c8af..19b7c4e 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
@@ -23,6 +23,20 @@
   // specified fragment.
   static Vector<NGPhysicalFragmentWithOffset> DescendantsOf(
       const NGPhysicalContainerFragment&);
+
+  // Returns list of inline fragments produced from the specified LayoutObject.
+  // The search is restricted in the subtree of |container|.
+  // Note: When |target| is a LayoutInline, some/all of its own box fragments
+  // may be absent from the fragment tree, in which case the nearest box/text
+  // descendant fragments are returned.
+  // Note 2: Most callers should use the enclosing block flow fragment of
+  // |target| as |container|. The only exception is
+  // LayoutInline::HitTestCulledInline().
+  // TODO(xiaochengh): As |container| is redundant in most cases, split this
+  // function into two variants that takes/omits |container|.
+  static Vector<NGPhysicalFragmentWithOffset> SelfFragmentsOf(
+      const NGPhysicalContainerFragment& container,
+      const LayoutObject* target);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 0c32caa..e7e454a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -77,8 +77,10 @@
 NGInlineBoxState* NGInlineLayoutAlgorithm::HandleOpenTag(
     const NGInlineItem& item,
     const NGInlineItemResult& item_result,
+    NGLineBoxFragmentBuilder::ChildList* line_box,
     NGInlineLayoutStateStack* box_states) const {
-  NGInlineBoxState* box = box_states->OnOpenTag(item, item_result, line_box_);
+  NGInlineBoxState* box =
+      box_states->OnOpenTag(item, item_result, baseline_type_, line_box);
   // Compute text metrics for all inline boxes since even empty inlines
   // influence the line height, except when quirks mode and the box is empty
   // for the purpose of empty block calculation.
@@ -160,12 +162,13 @@
   }
 
   // Create box states for tags that are not closed yet.
+  NGLineBoxFragmentBuilder::ChildList line_box;
   box_states->OnBeginPlaceItems(line_info.LineStyle(), baseline_type_,
-                                quirks_mode_);
+                                quirks_mode_, &line_box);
   for (const NGInlineItem* item : open_items) {
     NGInlineItemResult item_result;
     NGLineBreaker::ComputeOpenTagResult(*item, ConstraintSpace(), &item_result);
-    HandleOpenTag(*item, item_result, box_states);
+    HandleOpenTag(*item, item_result, &line_box, box_states);
   }
 }
 
@@ -175,9 +178,9 @@
     const NGInlineBreakToken* break_token) const {
   NGInlineLayoutStateStack rebuilt;
   RebuildBoxStates(line_info, break_token, &rebuilt);
-  rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_,
-                            quirks_mode_);
-
+  NGLineBoxFragmentBuilder::ChildList line_box;
+  rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_, quirks_mode_,
+                            &line_box);
   DCHECK(box_states_);
   box_states_->CheckSame(rebuilt);
 }
@@ -201,8 +204,8 @@
   // The baseline is adjusted after the height of the line box is computed.
   const ComputedStyle& line_style = line_info->LineStyle();
   box_states_->SetIsEmptyLine(line_info->IsEmptyLine());
-  NGInlineBoxState* box =
-      box_states_->OnBeginPlaceItems(line_style, baseline_type_, quirks_mode_);
+  NGInlineBoxState* box = box_states_->OnBeginPlaceItems(
+      line_style, baseline_type_, quirks_mode_, &line_box_);
 #if DCHECK_IS_ON()
   if (is_box_states_from_context_)
     CheckBoxStates(*line_info, BreakToken());
@@ -261,7 +264,7 @@
     } else if (item.Type() == NGInlineItem::kControl) {
       PlaceControlItem(item, *line_info, &item_result, box);
     } else if (item.Type() == NGInlineItem::kOpenTag) {
-      box = HandleOpenTag(item, item_result, box_states_);
+      box = HandleOpenTag(item, item_result, &line_box_, box_states_);
     } else if (item.Type() == NGInlineItem::kCloseTag) {
       box = HandleCloseTag(item, item_result, box);
     } else if (item.Type() == NGInlineItem::kAtomicInline) {
@@ -459,7 +462,8 @@
   // position += item_result->margins.LineLeft(style.Direction());
 
   item_result->has_edge = true;
-  NGInlineBoxState* box = box_states_->OnOpenTag(item, *item_result, line_box_);
+  NGInlineBoxState* box =
+      box_states_->OnOpenTag(item, *item_result, baseline_type_, line_box_);
   PlaceLayoutResult(item_result, box, box->margin_inline_start);
   return box_states_->OnCloseTag(&line_box_, box, baseline_type_);
 }
@@ -485,7 +489,8 @@
   LayoutUnit line_top = item_result->margins.line_over - metrics.ascent;
   line_box_.AddChild(std::move(item_result->layout_result),
                      LogicalOffset{inline_offset, line_top},
-                     item_result->inline_size, item.BidiLevel());
+                     item_result->inline_size, /* children_count */ 0,
+                     item.BidiLevel());
 }
 
 // Place all out-of-flow objects in |line_box_|.
@@ -1086,22 +1091,9 @@
 
   // For opaque items, copy bidi levels from adjacent items.
   if (has_opaque_items) {
-    UBiDiLevel last_level = levels.front();
-    if (last_level == kOpaqueBidiLevel) {
-      for (const UBiDiLevel level : levels) {
-        if (level != kOpaqueBidiLevel) {
-          last_level = level;
-          break;
-        }
-      }
-    }
-    // If all items are opaque, use the base direction.
-    if (last_level == kOpaqueBidiLevel) {
-      if (IsLtr(base_direction))
-        return;
-      last_level = 1;
-    }
-    for (UBiDiLevel& level : levels) {
+    // Use the paragraph level for trailing opaque items.
+    UBiDiLevel last_level = IsLtr(base_direction) ? 0 : 1;
+    for (UBiDiLevel& level : base::Reversed(levels)) {
       if (level == kOpaqueBidiLevel)
         level = last_level;
       else
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
index 71df67e..5eaebfe 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -69,6 +69,7 @@
 
   NGInlineBoxState* HandleOpenTag(const NGInlineItem&,
                                   const NGInlineItemResult&,
+                                  NGLineBoxFragmentBuilder::ChildList*,
                                   NGInlineLayoutStateStack*) const;
   NGInlineBoxState* HandleCloseTag(const NGInlineItem&,
                                    const NGInlineItemResult&,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
index 0080781..0f75cbff 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
@@ -82,6 +82,7 @@
     // The offset of the border box, initially in this child coordinate system.
     // |ComputeInlinePositions()| converts it to the offset within the line box.
     LogicalOffset offset;
+    LogicalSize size;
     // The offset of a positioned float wrt. the root BFC. This should only be
     // set for positioned floats.
     NGBfcOffset bfc_offset;
@@ -103,7 +104,8 @@
     Child() = default;
     // Create a placeholder. A placeholder does not have a fragment nor a bidi
     // level.
-    Child(LogicalOffset offset) : offset(offset) {}
+    Child(LayoutUnit block_offset, LayoutUnit block_size)
+        : offset(LayoutUnit(), block_offset), size(LayoutUnit(), block_size) {}
     // Crete a bidi control. A bidi control does not have a fragment, but has
     // bidi level and affects bidi reordering.
     Child(UBiDiLevel bidi_level) : bidi_level(bidi_level) {}
@@ -111,10 +113,12 @@
     Child(scoped_refptr<const NGLayoutResult> layout_result,
           LogicalOffset offset,
           LayoutUnit inline_size,
+          unsigned children_count,
           UBiDiLevel bidi_level)
         : layout_result(std::move(layout_result)),
           offset(offset),
           inline_size(inline_size),
+          children_count(children_count),
           bidi_level(bidi_level) {}
     // Create an in-flow |NGPhysicalTextFragment|.
     Child(scoped_refptr<const NGPhysicalTextFragment> fragment,
@@ -185,6 +189,12 @@
         return &layout_result->PhysicalFragment();
       return fragment.get();
     }
+    TextDirection ResolvedDirection() const {
+      // Inline boxes are not leaves that they don't have directions.
+      DCHECK(HasBidiLevel() || layout_result->PhysicalFragment().IsInlineBox());
+      return HasBidiLevel() ? DirectionFromLevel(bidi_level)
+                            : TextDirection::kLtr;
+    }
   };
 
   // A vector of Child.
@@ -235,10 +245,10 @@
     void InsertChild(unsigned index,
                      scoped_refptr<const NGLayoutResult> layout_result,
                      const LogicalOffset& offset,
-                     LayoutUnit inline_size,
-                     UBiDiLevel bidi_level) {
+                     unsigned children_count) {
       children_.insert(index, Child{std::move(layout_result), offset,
-                                    inline_size, bidi_level});
+                                    /* inline_size */ LayoutUnit(),
+                                    children_count, /* bidi_level */ 0});
     }
 
     void MoveInInlineDirection(LayoutUnit);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 103d785..d4a189e 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2930,6 +2930,8 @@
       box_geometry_has_been_invalidated, context));
 
   IntRect scroll_corner_and_resizer_visual_rect = ScrollCornerAndResizerRect();
+  scroll_corner_and_resizer_visual_rect.MoveBy(
+      RoundedIntPoint(box.FirstFragment().PaintOffset()));
   if (ScrollControlNeedsPaintInvalidation(
           scroll_corner_and_resizer_visual_rect,
           scroll_corner_and_resizer_visual_rect_,
@@ -3084,10 +3086,7 @@
 
 IntRect PaintLayerScrollableArea::ScrollCornerDisplayItemClient::VisualRect()
     const {
-  IntRect rect = scrollable_area_->ScrollCornerAndResizerRect();
-  rect.MoveBy(RoundedIntPoint(
-      scrollable_area_->GetLayoutBox()->FirstFragment().PaintOffset()));
-  return rect;
+  return scrollable_area_->scroll_corner_and_resizer_visual_rect_;
 }
 
 String PaintLayerScrollableArea::ScrollCornerDisplayItemClient::DebugName()
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
index 8ab810c..091cad2 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -388,19 +388,11 @@
   builder.AddNumber("encodedBodySize", encodedBodySize());
   builder.AddNumber("decodedBodySize", decodedBodySize());
 
-  HeapVector<ScriptValue> server_timing;
-  server_timing.ReserveCapacity(server_timing_.size());
-  for (const auto& timing : server_timing_) {
-    server_timing.push_back(timing->toJSONForBinding(builder.GetScriptState()));
-  }
-  builder.Add("serverTiming", server_timing);
-
-  HeapVector<ScriptValue> worker_timing;
-  worker_timing.ReserveCapacity(worker_timing_.size());
-  for (const auto& timing : worker_timing_) {
-    worker_timing.push_back(timing->toJSONForBinding(builder.GetScriptState()));
-  }
-  builder.Add("workerTiming", worker_timing);
+  ScriptState* script_state = builder.GetScriptState();
+  builder.Add("serverTiming", FreezeV8Object(ToV8(serverTiming(), script_state),
+                                             script_state->GetIsolate()));
+  builder.Add("workerTiming", FreezeV8Object(ToV8(workerTiming(), script_state),
+                                             script_state->GetIsolate()));
 }
 
 void PerformanceResourceTiming::AddPerformanceEntry(
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc
index 4419e27..1924298e 100644
--- a/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -220,9 +220,8 @@
 
 void WindowPerformance::BuildJSONValue(V8ObjectBuilder& builder) const {
   Performance::BuildJSONValue(builder);
-  builder.Add("timing", timing()->toJSONForBinding(builder.GetScriptState()));
-  builder.Add("navigation",
-              navigation()->toJSONForBinding(builder.GetScriptState()));
+  builder.Add("timing", timing());
+  builder.Add("navigation", navigation());
 }
 
 void WindowPerformance::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc
index b1561fd..4535974 100644
--- a/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -80,8 +80,9 @@
   void ResetPerformance() {
     page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
     page_holder_->GetDocument().SetURL(KURL("https://example.com"));
-    performance_ = MakeGarbageCollected<WindowPerformance>(
-        page_holder_->GetDocument().domWindow());
+
+    LocalDOMWindow* window = LocalDOMWindow::From(GetScriptState());
+    performance_ = DOMWindowPerformance::performance(*window);
     unified_clock_ = std::make_unique<Performance::UnifiedClock>(
         test_task_runner_->GetMockClock(),
         test_task_runner_->GetMockTickClock());
@@ -89,6 +90,10 @@
     performance_->time_origin_ = GetTimeOrigin();
   }
 
+  ScriptState* GetScriptState() const {
+    return ToScriptStateForMainWorld(page_holder_->GetDocument().GetFrame());
+  }
+
   Persistent<WindowPerformance> performance_;
   std::unique_ptr<DummyPageHolder> page_holder_;
   scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
@@ -190,7 +195,10 @@
 // Make sure the output entries with the same timestamps follow the insertion
 // order. (http://crbug.com/767560)
 TEST_F(WindowPerformanceTest, EnsureEntryListOrder) {
-  V8TestingScope scope;
+  // Need to have an active V8 context for ScriptValues to operate.
+  v8::HandleScope handle_scope(GetScriptState()->GetIsolate());
+  v8::Local<v8::Context> context = GetScriptState()->GetContext();
+  v8::Context::Scope context_scope(context);
   auto initial_offset =
       test_task_runner_->NowTicks().since_origin().InSecondsF();
   test_task_runner_->FastForwardBy(GetTimeOrigin() - base::TimeTicks());
@@ -198,12 +206,12 @@
   DummyExceptionStateForTesting exception_state;
   test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
   for (int i = 0; i < 8; i++) {
-    performance_->mark(scope.GetScriptState(), AtomicString::Number(i), nullptr,
+    performance_->mark(GetScriptState(), AtomicString::Number(i), nullptr,
                        exception_state);
   }
   test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
   for (int i = 8; i < 17; i++) {
-    performance_->mark(scope.GetScriptState(), AtomicString::Number(i), nullptr,
+    performance_->mark(GetScriptState(), AtomicString::Number(i), nullptr,
                        exception_state);
   }
   PerformanceEntryVector entries = performance_->getEntries();
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index 25f874429..df15771 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -860,18 +860,15 @@
   promises.resize(requests.size());
   for (wtf_size_t i = 0; i < requests.size(); ++i) {
     if (!requests[i]->url().ProtocolIsInHTTPFamily()) {
-      return ScriptPromise::Reject(script_state,
-                                   V8ThrowException::CreateTypeError(
-                                       script_state->GetIsolate(),
-                                       "Add/AddAll does not support schemes "
-                                       "other than \"http\" or \"https\""));
+      exception_state.ThrowTypeError(
+          "Add/AddAll does not support schemes "
+          "other than \"http\" or \"https\"");
+      return ScriptPromise();
     }
     if (requests[i]->method() != http_names::kGET) {
-      return ScriptPromise::Reject(
-          script_state,
-          V8ThrowException::CreateTypeError(
-              script_state->GetIsolate(),
-              "Add/AddAll only supports the GET request method."));
+      exception_state.ThrowTypeError(
+          "Add/AddAll only supports the GET request method.");
+      return ScriptPromise();
     }
     request_infos[i].SetRequest(requests[i]);
 
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_test.cc b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
index fe9b645..08bea31a 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_test.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
@@ -62,7 +62,7 @@
   ScriptPromise Fetch(ScriptState* script_state,
                       const RequestInfo& request_info,
                       const RequestInit*,
-                      ExceptionState&) override {
+                      ExceptionState& exception_state) override {
     ++fetch_count_;
     if (expected_url_) {
       String fetched_url;
@@ -80,10 +80,9 @@
       response_ = nullptr;
       return promise;
     }
-    return ScriptPromise::Reject(
-        script_state, V8ThrowException::CreateTypeError(
-                          script_state->GetIsolate(),
-                          "Unexpected call to fetch, no response available."));
+    exception_state.ThrowTypeError(
+        "Unexpected call to fetch, no response available.");
+    return ScriptPromise();
   }
 
   // This does not take ownership of its parameter. The provided sample object
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
index 59dd47d..bd58a33 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -62,21 +62,25 @@
   // If PopulateForNewEvent is called, it sets trace_event_name_ to
   // trace_event_name. Otherwise, trace_event_name_ is nullptr, so this instance
   // is considered empty. This roundabout initialization lets us avoid calling
-  // TRACE_EVENT_ASYNC_END0 with an uninitalized ID.
-  TRACE_EVENT_ASYNC_BEGIN0("IndexedDB", trace_event_name,
-                           PopulateForNewEvent(trace_event_name));
+  // TRACE_EVENT_NESTABLE_ASYNC_END0 with an uninitalized ID.
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+      "IndexedDB", trace_event_name,
+      TRACE_ID_LOCAL(PopulateForNewEvent(trace_event_name)));
 }
 
 void IDBRequest::AsyncTraceState::RecordAndReset() {
   if (trace_event_name_) {
-    TRACE_EVENT_ASYNC_END0("IndexedDB", trace_event_name_, id_);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("IndexedDB", trace_event_name_,
+                                    TRACE_ID_LOCAL(id_));
     trace_event_name_ = nullptr;
   }
 }
 
 IDBRequest::AsyncTraceState::~AsyncTraceState() {
-  if (trace_event_name_)
-    TRACE_EVENT_ASYNC_END0("IndexedDB", trace_event_name_, id_);
+  if (trace_event_name_) {
+    TRACE_EVENT_NESTABLE_ASYNC_END0("IndexedDB", trace_event_name_,
+                                    TRACE_ID_LOCAL(id_));
+  }
 }
 
 size_t IDBRequest::AsyncTraceState::PopulateForNewEvent(
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.h b/third_party/blink/renderer/modules/indexeddb/idb_request.h
index 48a337ea..291b57a 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -74,20 +74,21 @@
   using Source = IDBObjectStoreOrIDBIndexOrIDBCursor;
   // Container for async tracing state.
   //
-  // The documentation for TRACE_EVENT_ASYNC_{BEGIN,END} suggests identifying
-  // trace events by using pointers or a counter that is always incremented on
-  // the same thread. This is not viable for IndexedDB, because the same object
-  // can result in multiple trace events (requests associated with cursors), and
-  // IndexedDB can be used from multiple threads in the same renderer (workers).
-  // Furthermore, we want to record the beginning event of an async trace right
-  // when we start serving an IDB API call, before the IDBRequest object is
-  // created, so we can't rely on information in an IDBRequest.
+  // The documentation for TRACE_EVENT_NESTABLE_ASYNC_{BEGIN,END} suggests
+  // identifying trace events by using pointers or a counter that is always
+  // incremented on the same thread. This is not viable for IndexedDB, because
+  // the same object can result in multiple trace events (requests associated
+  // with cursors), and IndexedDB can be used from multiple threads in the same
+  // renderer (workers). Furthermore, we want to record the beginning event of
+  // an async trace right when we start serving an IDB API call, before the
+  // IDBRequest object is created, so we can't rely on information in an
+  // IDBRequest.
   //
   // This class solves the ID uniqueness problem by relying on an atomic counter
   // to generating unique IDs in a threadsafe manner. The atomic machinery is
   // used when tracing is enabled. The recording problem is solved by having
   // instances of this class store the information needed to record async trace
-  // end events (via TRACE_EVENT_ASYNC_END).
+  // end events (via TRACE_EVENT_NESTABLE_ASYNC_END).
   //
   // From a mechanical perspective, creating an AsyncTraceState instance records
   // the beginning event of an async trace. The instance is then moved into an
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index 2b5ca1f0..a7902d9 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -398,7 +398,8 @@
 
 void MediaSource::SetWebMediaSourceAndOpen(
     std::unique_ptr<WebMediaSource> web_media_source) {
-  TRACE_EVENT_ASYNC_END0("media", "MediaSource::attachToElement", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "MediaSource::attachToElement",
+                                  TRACE_ID_LOCAL(this));
   DCHECK(web_media_source);
   DCHECK(!web_media_source_);
   DCHECK(attached_element_);
@@ -843,7 +844,8 @@
 
   DCHECK(IsClosed());
 
-  TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSource::attachToElement", this);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "MediaSource::attachToElement",
+                                    TRACE_ID_LOCAL(this));
   attached_element_ = element;
   return true;
 }
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.cc b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
index a69ae89..f124d27 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -480,7 +480,8 @@
     return;
   }
 
-  TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::remove", this);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "SourceBuffer::remove",
+                                    TRACE_ID_LOCAL(this));
 
   // 6. If the readyState attribute of the parent media source is in the "ended"
   //    state then run the following steps:
@@ -609,7 +610,8 @@
     ScheduleEvent(event_type_names::kUpdateend);
   }
 
-  TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::remove", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::remove",
+                                  TRACE_ID_LOCAL(this));
 }
 
 void SourceBuffer::AbortIfUpdating() {
@@ -640,7 +642,8 @@
   //      SourceBuffer object.
   ScheduleEvent(event_type_names::kUpdateend);
 
-  TRACE_EVENT_ASYNC_END0("media", trace_event_name, this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", trace_event_name,
+                                  TRACE_ID_LOCAL(this));
 }
 
 void SourceBuffer::RemovedFromMediaSource() {
@@ -1190,7 +1193,8 @@
 bool SourceBuffer::PrepareAppend(double media_time,
                                  size_t new_data_size,
                                  ExceptionState& exception_state) {
-  TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::prepareAppend", this);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "SourceBuffer::prepareAppend",
+                                    TRACE_ID_LOCAL(this));
   // http://w3c.github.io/media-source/#sourcebuffer-prepare-append
   // 3.5.4 Prepare Append Algorithm
   // 1. If the SourceBuffer has been removed from the sourceBuffers attribute of
@@ -1200,7 +1204,8 @@
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
                                         exception_state)) {
-    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::prepareAppend",
+                                    TRACE_ID_LOCAL(this));
     return false;
   }
 
@@ -1212,7 +1217,8 @@
     MediaSource::LogAndThrowDOMException(
         exception_state, DOMExceptionCode::kInvalidStateError,
         "The HTMLMediaElement.error attribute is not null.");
-    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::prepareAppend",
+                                    TRACE_ID_LOCAL(this));
     return false;
   }
 
@@ -1236,11 +1242,13 @@
                                          "The SourceBuffer is full, and cannot "
                                          "free space to append additional "
                                          "buffers.");
-    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::prepareAppend",
+                                    TRACE_ID_LOCAL(this));
     return false;
   }
 
-  TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::prepareAppend",
+                                  TRACE_ID_LOCAL(this));
   return true;
 }
 
@@ -1268,18 +1276,19 @@
                                         const unsigned char* data,
                                         size_t size,
                                         ExceptionState& exception_state) {
-  TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size",
-                           size);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer",
+                                    TRACE_ID_LOCAL(this), "size", size);
   // Section 3.2 appendBuffer()
   // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
 
   // 1. Run the prepare append algorithm.
   if (!PrepareAppend(media_time, size, exception_state)) {
-    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::appendBuffer",
+                                    TRACE_ID_LOCAL(this));
     return;
   }
-  TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this,
-                               "prepareAppend");
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "prepareAppend",
+                                    TRACE_ID_LOCAL(this));
 
   // 2. Add data to the end of the input buffer.
   DCHECK(data || size == 0);
@@ -1300,8 +1309,10 @@
       FROM_HERE,
       WTF::Bind(&SourceBuffer::AppendBufferAsyncPart, WrapPersistent(this)));
 
-  TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this,
-                               "initialDelay");
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "prepareAppend",
+                                  TRACE_ID_LOCAL(this));
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "delay", TRACE_ID_LOCAL(this),
+                                    "type", "initialDelay");
 }
 
 void SourceBuffer::AppendBufferAsyncPart() {
@@ -1325,8 +1336,9 @@
   if (append_size > kMaxAppendSize)
     append_size = kMaxAppendSize;
 
-  TRACE_EVENT_ASYNC_STEP_INTO1("media", "SourceBuffer::appendBuffer", this,
-                               "appending", "appendSize", append_size);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "delay", TRACE_ID_LOCAL(this));
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "appending", TRACE_ID_LOCAL(this),
+                                    "appendSize", append_size);
 
   // |zero| is used for 0 byte appends so we always have a valid pointer.
   // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer|
@@ -1352,8 +1364,10 @@
           FROM_HERE,
           WTF::Bind(&SourceBuffer::AppendBufferAsyncPart,
                     WrapPersistent(this)));
-      TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this,
-                                   "nextPieceDelay");
+      TRACE_EVENT_NESTABLE_ASYNC_END0("media", "appending",
+                                      TRACE_ID_LOCAL(this));
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "delay", TRACE_ID_LOCAL(this),
+                                        "type", "nextPieceDelay");
       return;
     }
 
@@ -1371,7 +1385,10 @@
     ScheduleEvent(event_type_names::kUpdateend);
   }
 
-  TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "appending", TRACE_ID_LOCAL(this));
+  TRACE_EVENT_NESTABLE_ASYNC_END0("media", "SourceBuffer::appendBuffer",
+                                  TRACE_ID_LOCAL(this));
+
   double media_time = GetMediaTime();
   DVLOG(3) << __func__ << " done. this=" << this << " media_time=" << media_time
            << " buffered="
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 83bfe43..3505661 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
@@ -260,8 +260,8 @@
   // PeerConnectionFactory::CreateVideoTrack doesn't do reference counting.
   video_source_proxy_ =
       factory->CreateVideoTrackSourceProxy(video_source_.get());
-  video_track_ = factory->CreateLocalVideoTrack(track.Id().Utf8(),
-                                                video_source_proxy_.get());
+  video_track_ =
+      factory->CreateLocalVideoTrack(track.Id(), video_source_proxy_.get());
 
   video_track_->set_content_hint(
       ContentHintTypeToWebRtcContentHint(track.ContentHint()));
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
index 87711d5..2f3470c 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
@@ -404,35 +404,34 @@
 }
 scoped_refptr<webrtc::MediaStreamInterface>
 MockPeerConnectionDependencyFactory::CreateLocalMediaStream(
-    const std::string& label) {
-  return new rtc::RefCountedObject<MockMediaStream>(label);
+    const String& label) {
+  return new rtc::RefCountedObject<MockMediaStream>(label.Utf8());
 }
 
 scoped_refptr<webrtc::VideoTrackInterface>
 MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
-    const std::string& id,
+    const String& id,
     webrtc::VideoTrackSourceInterface* source) {
   scoped_refptr<webrtc::VideoTrackInterface> track(
-      new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, source));
+      new rtc::RefCountedObject<MockWebRtcVideoTrack>(id.Utf8(), source));
   return track;
 }
 
 SessionDescriptionInterface*
 MockPeerConnectionDependencyFactory::CreateSessionDescription(
-    const std::string& type,
-    const std::string& sdp,
+    const String& type,
+    const String& sdp,
     webrtc::SdpParseError* error) {
   if (fail_to_create_session_description_)
     return nullptr;
-  return new MockSessionDescription(type, sdp);
+  return new MockSessionDescription(type.Utf8(), sdp.Utf8());
 }
 
 webrtc::IceCandidateInterface*
-MockPeerConnectionDependencyFactory::CreateIceCandidate(
-    const std::string& sdp_mid,
-    int sdp_mline_index,
-    const std::string& sdp) {
-  return new MockIceCandidate(sdp_mid, sdp_mline_index, sdp);
+MockPeerConnectionDependencyFactory::CreateIceCandidate(const String& sdp_mid,
+                                                        int sdp_mline_index,
+                                                        const String& sdp) {
+  return new MockIceCandidate(sdp_mid.Utf8(), sdp_mline_index, sdp.Utf8());
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
index 7175b11..e93141e5 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
@@ -172,18 +172,17 @@
   scoped_refptr<webrtc::VideoTrackSourceInterface> CreateVideoTrackSourceProxy(
       webrtc::VideoTrackSourceInterface* source) override;
   scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
-      const std::string& label) override;
+      const String& label) override;
   scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
-      const std::string& id,
+      const String& id,
       webrtc::VideoTrackSourceInterface* source) override;
   webrtc::SessionDescriptionInterface* CreateSessionDescription(
-      const std::string& type,
-      const std::string& sdp,
+      const String& type,
+      const String& sdp,
       webrtc::SdpParseError* error) override;
-  webrtc::IceCandidateInterface* CreateIceCandidate(
-      const std::string& sdp_mid,
-      int sdp_mline_index,
-      const std::string& sdp) override;
+  webrtc::IceCandidateInterface* CreateIceCandidate(const String& sdp_mid,
+                                                    int sdp_mline_index,
+                                                    const String& sdp) override;
 
   scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcSignalingTaskRunner()
       override;
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 3899e2a..ffa4726 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
@@ -7,10 +7,10 @@
 #include <stddef.h>
 
 #include <memory>
+#include <string>
 #include <utility>
 #include <vector>
 
-#include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -49,6 +49,8 @@
 #include "third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h"
 #include "third_party/blink/renderer/platform/peerconnection/stun_field_trial.h"
 #include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.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"
 #include "third_party/webrtc/api/call/call_factory_interface.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory.h"
@@ -73,13 +75,12 @@
   DISABLE_NON_PROXIED_UDP,
 };
 
-WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy(
-    const std::string& preference) {
-  if (preference == blink::kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces)
+WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy(const String& preference) {
+  if (preference == kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces)
     return DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES;
-  if (preference == blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly)
+  if (preference == kWebRTCIPHandlingDefaultPublicInterfaceOnly)
     return DEFAULT_PUBLIC_INTERFACE_ONLY;
-  if (preference == blink::kWebRTCIPHandlingDisableNonProxiedUdp)
+  if (preference == kWebRTCIPHandlingDisableNonProxiedUdp)
     return DISABLE_NON_PROXIED_UDP;
   return DEFAULT;
 }
@@ -194,11 +195,12 @@
   base::WaitableEvent start_worker_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
-  chrome_worker_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PeerConnectionDependencyFactory::InitializeWorkerThread,
-                     base::Unretained(this), &worker_thread_,
-                     &start_worker_event));
+  PostCrossThreadTask(
+      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+      CrossThreadBindOnce(
+          &PeerConnectionDependencyFactory::InitializeWorkerThread,
+          CrossThreadUnretained(this), CrossThreadUnretained(&worker_thread_),
+          CrossThreadUnretained(&start_worker_event)));
 
   base::WaitableEvent create_network_manager_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
@@ -212,12 +214,13 @@
     mdns_responder = std::make_unique<MdnsResponderAdapter>();
   }
 #endif  // BUILDFLAG(ENABLE_MDNS)
-  chrome_worker_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PeerConnectionDependencyFactory::
-                         CreateIpcNetworkManagerOnWorkerThread,
-                     base::Unretained(this), &create_network_manager_event,
-                     std::move(mdns_responder)));
+  PostCrossThreadTask(
+      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+      CrossThreadBindOnce(&PeerConnectionDependencyFactory::
+                              CreateIpcNetworkManagerOnWorkerThread,
+                          CrossThreadUnretained(this),
+                          CrossThreadUnretained(&create_network_manager_event),
+                          std::move(mdns_responder)));
 
   start_worker_event.Wait();
   create_network_manager_event.Wait();
@@ -234,12 +237,13 @@
   base::WaitableEvent start_signaling_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
-  chrome_signaling_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
+  PostCrossThreadTask(
+      *chrome_signaling_thread_.task_runner().get(), FROM_HERE,
+      CrossThreadBindOnce(
           &PeerConnectionDependencyFactory::InitializeSignalingThread,
-          base::Unretained(this), blink::Platform::Current()->GetGpuFactories(),
-          &start_signaling_event));
+          CrossThreadUnretained(this),
+          CrossThreadUnretained(Platform::Current()->GetGpuFactories()),
+          CrossThreadUnretained(&start_signaling_event)));
 
   start_signaling_event.Wait();
   CHECK(signaling_thread_);
@@ -395,14 +399,14 @@
   // detached, it is impossible for RTCPeerConnectionHandler to outlive the
   // frame. Therefore using a raw pointer of |media_permission| is safe here.
   media::MediaPermission* media_permission = nullptr;
-  if (!blink::Platform::Current()->ShouldEnforceWebRTCRoutingPreferences()) {
+  if (!Platform::Current()->ShouldEnforceWebRTCRoutingPreferences()) {
     port_config.enable_multiple_routes = true;
     port_config.enable_nonproxied_udp = true;
     VLOG(3) << "WebRTC routing preferences will not be enforced";
   } else {
     if (web_frame && web_frame->View()) {
-      blink::WebString webrtc_ip_handling_policy;
-      blink::Platform::Current()->GetWebRTCRendererPreferences(
+      WebString webrtc_ip_handling_policy;
+      Platform::Current()->GetWebRTCRendererPreferences(
           web_frame, &webrtc_ip_handling_policy, &min_port, &max_port,
           &allow_mdns_obfuscation);
 
@@ -411,7 +415,7 @@
       // collected depends on if mic/camera permission is granted for this
       // origin.
       WebRTCIPHandlingPolicy policy =
-          GetWebRTCIPHandlingPolicy(webrtc_ip_handling_policy.Utf8());
+          GetWebRTCIPHandlingPolicy(webrtc_ip_handling_policy);
       switch (policy) {
         // TODO(guoweis): specify the flag of disabling local candidate
         // collection when webrtc is updated.
@@ -480,9 +484,8 @@
 }
 
 scoped_refptr<webrtc::MediaStreamInterface>
-PeerConnectionDependencyFactory::CreateLocalMediaStream(
-    const std::string& label) {
-  return GetPcFactory()->CreateLocalMediaStream(label).get();
+PeerConnectionDependencyFactory::CreateLocalMediaStream(const String& label) {
+  return GetPcFactory()->CreateLocalMediaStream(label.Utf8()).get();
 }
 
 scoped_refptr<webrtc::VideoTrackSourceInterface>
@@ -500,24 +503,25 @@
 
 scoped_refptr<webrtc::VideoTrackInterface>
 PeerConnectionDependencyFactory::CreateLocalVideoTrack(
-    const std::string& id,
+    const String& id,
     webrtc::VideoTrackSourceInterface* source) {
-  return GetPcFactory()->CreateVideoTrack(id, source).get();
+  return GetPcFactory()->CreateVideoTrack(id.Utf8(), source).get();
 }
 
 webrtc::SessionDescriptionInterface*
 PeerConnectionDependencyFactory::CreateSessionDescription(
-    const std::string& type,
-    const std::string& sdp,
+    const String& type,
+    const String& sdp,
     webrtc::SdpParseError* error) {
-  return webrtc::CreateSessionDescription(type, sdp, error);
+  return webrtc::CreateSessionDescription(type.Utf8(), sdp.Utf8(), error);
 }
 
 webrtc::IceCandidateInterface*
-PeerConnectionDependencyFactory::CreateIceCandidate(const std::string& sdp_mid,
+PeerConnectionDependencyFactory::CreateIceCandidate(const String& sdp_mid,
                                                     int sdp_mline_index,
-                                                    const std::string& sdp) {
-  return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp, nullptr);
+                                                    const String& sdp) {
+  return webrtc::CreateIceCandidate(sdp_mid.Utf8(), sdp_mline_index, sdp.Utf8(),
+                                    nullptr);
 }
 
 blink::WebRtcAudioDeviceImpl*
@@ -537,27 +541,29 @@
 }
 
 void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
-  base::Optional<std::string> params =
-      blink::Platform::Current()->WebRtcStunProbeTrialParameter();
+  base::Optional<WebString> params =
+      Platform::Current()->WebRtcStunProbeTrialParameter();
   if (!params)
     return;
 
   GetPcFactory();
 
-  chrome_worker_thread_.task_runner()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(
+  PostDelayedCrossThreadTask(
+      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+      CrossThreadBindOnce(
           &PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread,
-          base::Unretained(this), *params),
+          CrossThreadUnretained(this), String(*params)),
       base::TimeDelta::FromMilliseconds(blink::kExperimentStartDelayMs));
 }
 
 void PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread(
-    const std::string& params) {
+    const String& params) {
   DCHECK(network_manager_);
   DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
-  stun_trial_.reset(new blink::StunProberTrial(network_manager_.get(), params,
-                                               socket_factory_.get()));
+  // 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(
@@ -581,11 +587,11 @@
     // The network manager needs to free its resources on the thread they were
     // created, which is the worked thread.
     if (chrome_worker_thread_.IsRunning()) {
-      chrome_worker_thread_.task_runner()->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+          CrossThreadBindOnce(
               &PeerConnectionDependencyFactory::DeleteIpcNetworkManager,
-              base::Unretained(this)));
+              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.
@@ -626,8 +632,7 @@
 }
 
 std::unique_ptr<webrtc::RtpCapabilities>
-PeerConnectionDependencyFactory::GetSenderCapabilities(
-    const std::string& kind) {
+PeerConnectionDependencyFactory::GetSenderCapabilities(const String& kind) {
   if (kind == "audio") {
     return std::make_unique<webrtc::RtpCapabilities>(
         GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO));
@@ -639,8 +644,7 @@
 }
 
 std::unique_ptr<webrtc::RtpCapabilities>
-PeerConnectionDependencyFactory::GetReceiverCapabilities(
-    const std::string& kind) {
+PeerConnectionDependencyFactory::GetReceiverCapabilities(const String& kind) {
   if (kind == "audio") {
     return std::make_unique<webrtc::RtpCapabilities>(
         GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO));
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 6f0d8e1..05d6ab23 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
@@ -5,14 +5,13 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
 
-#include <string>
-
 #include "base/macros.h"
 #include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/p2p/stunprober/stun_prober.h"
 
@@ -70,11 +69,11 @@
 
   // Asks the PeerConnection factory to create a Local MediaStream object.
   virtual scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
-      const std::string& label);
+      const String& label);
 
   // Asks the PeerConnection factory to create a Local VideoTrack object.
   virtual scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
-      const std::string& id,
+      const String& id,
       webrtc::VideoTrackSourceInterface* source);
 
   // Asks the libjingle PeerConnection factory to create a libjingle
@@ -97,22 +96,22 @@
   // Creates a libjingle representation of a Session description. Used by a
   // RTCPeerConnectionHandler instance.
   virtual webrtc::SessionDescriptionInterface* CreateSessionDescription(
-      const std::string& type,
-      const std::string& sdp,
+      const String& type,
+      const String& sdp,
       webrtc::SdpParseError* error);
 
   // Creates a libjingle representation of an ice candidate.
   virtual webrtc::IceCandidateInterface* CreateIceCandidate(
-      const std::string& sdp_mid,
+      const String& sdp_mid,
       int sdp_mline_index,
-      const std::string& sdp);
+      const String& sdp);
 
   // Returns the most optimistic view of the capabilities of the system for
   // sending or receiving media of the given kind ("audio" or "video").
   virtual std::unique_ptr<webrtc::RtpCapabilities> GetSenderCapabilities(
-      const std::string& kind);
+      const String& kind);
   virtual std::unique_ptr<webrtc::RtpCapabilities> GetReceiverCapabilities(
-      const std::string& kind);
+      const String& kind);
 
   blink::WebRtcAudioDeviceImpl* GetWebRtcAudioDevice();
 
@@ -142,7 +141,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 std::string& params);
+  void StartStunProbeTrialOnWorkerThread(const String& params);
 
   // Creates |pc_factory_|, which in turn is used for
   // creating PeerConnection objects.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index c5aca0e5..0578d21d 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -310,7 +310,8 @@
                 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
       : request_(request.get()), main_thread_(task_runner) {
     // Measure the overall time it takes to satisfy a getStats request.
-    TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("webrtc", "getStats_Native",
+                                      TRACE_ID_LOCAL(this));
     DETACH_FROM_THREAD(signaling_thread_checker_);
   }
 
@@ -429,7 +430,8 @@
     // Record the getStats operation as done before calling into Blink so that
     // we don't skew the perf measurements of the native code with whatever the
     // callback might be doing.
-    TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("webrtc", "getStats_Native",
+                                    TRACE_ID_LOCAL(this));
     request_->requestSucceeded(response);
     request_ = nullptr;  // must be freed on the main thread.
   }
@@ -1550,11 +1552,11 @@
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
   std::unique_ptr<webrtc::IceCandidateInterface> native_candidate(
       dependency_factory_->CreateIceCandidate(
-          candidate->SdpMid().Utf8(),
+          candidate->SdpMid(),
           candidate->SdpMLineIndex()
               ? static_cast<int>(*candidate->SdpMLineIndex())
               : -1,
-          candidate->Candidate().Utf8()));
+          candidate->Candidate()));
 
   auto callback_on_task_runner =
       [](base::WeakPtr<RTCPeerConnectionHandler> handler_weak_ptr,
@@ -2444,8 +2446,7 @@
     const String& type,
     webrtc::SdpParseError* error) {
   webrtc::SessionDescriptionInterface* native_desc =
-      dependency_factory_->CreateSessionDescription(type.Utf8(), sdp.Utf8(),
-                                                    error);
+      dependency_factory_->CreateSessionDescription(type, sdp, error);
 
   LOG_IF(ERROR, !native_desc) << "Failed to create native session description."
                               << " Type: " << type << " SDP: " << sdp;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
index 8a24d077..7beab96 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
@@ -309,8 +309,7 @@
   }
 
   // Creates a WebKit local MediaStream.
-  blink::WebMediaStream CreateLocalMediaStream(
-      const std::string& stream_label) {
+  WebMediaStream CreateLocalMediaStream(const std::string& stream_label) {
     std::string video_track_label("video-label");
     std::string audio_track_label("audio-label");
     blink::WebMediaStreamSource blink_audio_source;
@@ -373,18 +372,18 @@
   // Creates a remote MediaStream and adds it to the mocked native
   // peer connection.
   rtc::scoped_refptr<webrtc::MediaStreamInterface> AddRemoteMockMediaStream(
-      const std::string& stream_label,
-      const std::string& video_track_label,
-      const std::string& audio_track_label) {
+      const String& stream_label,
+      const String& video_track_label,
+      const String& audio_track_label) {
     rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
         mock_dependency_factory_->CreateLocalMediaStream(stream_label).get());
-    if (!video_track_label.empty()) {
+    if (!video_track_label.IsEmpty()) {
       InvokeAddTrack(
-          stream, blink::MockWebRtcVideoTrack::Create(video_track_label).get());
+          stream, MockWebRtcVideoTrack::Create(video_track_label.Utf8()).get());
     }
-    if (!audio_track_label.empty()) {
+    if (!audio_track_label.IsEmpty()) {
       InvokeAddTrack(
-          stream, blink::MockWebRtcAudioTrack::Create(audio_track_label).get());
+          stream, MockWebRtcAudioTrack::Create(audio_track_label.Utf8()).get());
     }
     mock_peer_connection_->AddRemoteStream(stream);
     return stream;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index c5b2bf3..65e6a7f 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -193,7 +193,7 @@
 
   std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
       PeerConnectionDependencyFactory::GetInstance()->GetSenderCapabilities(
-          kind.Utf8());
+          kind);
 
   HeapVector<Member<RTCRtpCodecCapability>> codecs;
   codecs.ReserveInitialCapacity(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 3556110..ef4780d 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -580,7 +580,7 @@
 
   std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
       PeerConnectionDependencyFactory::GetInstance()->GetSenderCapabilities(
-          kind.Utf8());
+          kind);
 
   HeapVector<Member<RTCRtpCodecCapability>> codecs;
   codecs.ReserveInitialCapacity(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
index ed45d15ab..5ee62cfe 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
@@ -184,9 +184,9 @@
     size_t script_size,
     size_t cached_metadata_size) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
-  TRACE_EVENT_ASYNC_BEGIN0(
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
       "ServiceWorker", "ServiceWorkerGlobalScopeProxy::EvaluateClassicScript",
-      this);
+      TRACE_ID_LOCAL(this));
   // TODO(asamidoi): Remove CountWorkerScript which is called for recording
   // metrics if the metrics are no longer referenced, and then merge
   // WillEvaluateClassicScript and WillEvaluateModuleScript for cleanup.
@@ -217,9 +217,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->DidEvaluateScript();
   Client().DidEvaluateScript(success);
-  TRACE_EVENT_ASYNC_END1("ServiceWorker",
-                         "ServiceWorkerGlobalScopeProxy::EvaluateClassicScript",
-                         this, "success", success);
+  TRACE_EVENT_NESTABLE_ASYNC_END1(
+      "ServiceWorker", "ServiceWorkerGlobalScopeProxy::EvaluateClassicScript",
+      TRACE_ID_LOCAL(this), "success", success);
 }
 
 void ServiceWorkerGlobalScopeProxy::DidEvaluateModuleScript(bool success) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
index 8aef6a0..5cae7e46 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
@@ -80,16 +80,6 @@
   Member<WebGLVideoTexture> webgl_video_texture_;
 };
 
-DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContext,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
-                          Platform::kWebGL2ComputeContextType,
-                  context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          Platform::kWebGL2ComputeContextType);
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
index 0953f26..3a06569 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -126,16 +126,6 @@
   HeapVector<Member<WebGLBuffer>> bound_indexed_shader_storage_buffers_;
 };
 
-DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContextBase,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
-                          Platform::kWebGL2ComputeContextType,
-                  context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          Platform::kWebGL2ComputeContextType);
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
index 33aec329..72aa8f63 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
@@ -90,16 +90,6 @@
   Member<WebGLVideoTexture> webgl_video_texture_;
 };
 
-DEFINE_TYPE_CASTS(WebGL2RenderingContext,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
-                          Platform::kWebGL2ContextType,
-                  context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          Platform::kWebGL2ContextType);
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
index e0a262b..d8a6e544 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
@@ -1146,16 +1146,6 @@
   GLint unpack_skip_images_;
 };
 
-DEFINE_TYPE_CASTS(WebGL2RenderingContextBase,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
-                          Platform::kWebGL2ContextType,
-                  context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          Platform::kWebGL2ContextType);
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
index 3bf24b7..4e2a4a2 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
@@ -132,16 +132,6 @@
   Member<WebGLVideoTexture> webgl_video_texture_;
 };
 
-DEFINE_TYPE_CASTS(WebGLRenderingContext,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
-                          Platform::kWebGL1ContextType,
-                  context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          Platform::kWebGL1ContextType);
-
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERING_CONTEXT_H_
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 65b93ca..bb281df6 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -792,12 +792,12 @@
 }
 
 ScriptPromise WebGLRenderingContextBase::makeXRCompatible(
-    ScriptState* script_state) {
+    ScriptState* script_state,
+    ExceptionState& exception_state) {
   if (isContextLost()) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        MakeGarbageCollected<DOMException>(DOMExceptionCode::kInvalidStateError,
-                                           "Context lost."));
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "Context lost.");
+    return ScriptPromise();
   }
 
   if (xr_compatible_) {
@@ -812,11 +812,10 @@
 
   // TODO(http://crbug.com/876140) Trigger context loss and recreate on
   // compatible GPU.
-  return ScriptPromise::RejectWithDOMException(
-      script_state,
-      MakeGarbageCollected<DOMException>(
-          DOMExceptionCode::kNotSupportedError,
-          "Context is not compatible. Switching not yet implemented."));
+  exception_state.ThrowDOMException(
+      DOMExceptionCode::kNotSupportedError,
+      "Context is not compatible. Switching not yet implemented.");
+  return ScriptPromise();
 }
 
 bool WebGLRenderingContextBase::IsXRCompatible() {
@@ -5435,7 +5434,7 @@
   // (e.g. CanUseTexImageViaGPU returning false).
   if (is_webgl_canvas && upload_via_gpu) {
     source_canvas_webgl_context =
-        ToWebGLRenderingContextBase(context_host->RenderingContext());
+        To<WebGLRenderingContextBase>(context_host->RenderingContext());
   } else {
     image = context_host->GetSourceImageForCanvas(
         &source_image_status, kPreferAcceleration,
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index f7b41f8e..976de54b 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -606,7 +606,7 @@
 
   void commit();
 
-  ScriptPromise makeXRCompatible(ScriptState*);
+  ScriptPromise makeXRCompatible(ScriptState*, ExceptionState&);
   bool IsXRCompatible();
 
   void UpdateNumberOfUserAllocatedMultisampledRenderbuffers(int delta);
@@ -1767,12 +1767,12 @@
   DISALLOW_COPY_AND_ASSIGN(WebGLRenderingContextBase);
 };
 
-// TODO(fserb): remove this.
-DEFINE_TYPE_CASTS(WebGLRenderingContextBase,
-                  CanvasRenderingContext,
-                  context,
-                  context->Is3d(),
-                  context.Is3d());
+template <>
+struct DowncastTraits<WebGLRenderingContextBase> {
+  static bool AllowFrom(const CanvasRenderingContext& context) {
+    return context.Is3d();
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
index 60824477..88259a3 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
@@ -709,5 +709,5 @@
     [RuntimeEnabled=OffscreenCanvasCommit] void commit();
 
     // WebXR Device API support
-    [RuntimeEnabled=WebXR, SecureContext, CallWith=ScriptState] Promise<void> makeXRCompatible();
+    [RuntimeEnabled=WebXR, SecureContext, CallWith=ScriptState, RaisesException] Promise<void> makeXRCompatible();
 };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 35c12fd4..ead70cf4 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -449,6 +449,7 @@
     "bindings/v8_dom_wrapper.cc",
     "bindings/v8_dom_wrapper.h",
     "bindings/v8_global_value_map.h",
+    "bindings/v8_interface_bridge.h",
     "bindings/v8_object_constructor.cc",
     "bindings/v8_object_constructor.h",
     "bindings/v8_per_context_data.cc",
diff --git a/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h b/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h
new file mode 100644
index 0000000..f182edb7
--- /dev/null
+++ b/third_party/blink/renderer/platform/bindings/v8_interface_bridge.h
@@ -0,0 +1,55 @@
+// 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_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class DOMWrapperWorld;
+
+namespace bindings {
+
+// The common base class of code-generated V8-Blink bridge class of IDL
+// interfaces and namespaces.
+class PLATFORM_EXPORT V8InterfaceBridgeBase {
+  STATIC_ONLY(V8InterfaceBridgeBase);
+
+ protected:
+  using InstallInterfaceTemplateFuncType =
+      void (*)(v8::Isolate* isolate,
+               const DOMWrapperWorld& world,
+               v8::Local<v8::FunctionTemplate> interface_template);
+  using InstallUnconditionalPropertiesFuncType =
+      void (*)(v8::Isolate* isolate,
+               const DOMWrapperWorld& world,
+               v8::Local<v8::ObjectTemplate> instance_template,
+               v8::Local<v8::ObjectTemplate> prototype_template,
+               v8::Local<v8::FunctionTemplate> interface_template);
+  using InstallContextIndependentPropertiesFuncType =
+      void (*)(v8::Isolate* isolate,
+               const DOMWrapperWorld& world,
+               v8::Local<v8::ObjectTemplate> instance_template,
+               v8::Local<v8::ObjectTemplate> prototype_template,
+               v8::Local<v8::FunctionTemplate> interface_template);
+  using InstallContextDependentPropertiesFuncType =
+      void (*)(v8::Local<v8::Context> context,
+               const DOMWrapperWorld& world,
+               v8::Local<v8::Object> instance_object,
+               v8::Local<v8::Object> prototype_object,
+               v8::Local<v8::Function> interface_object);
+};
+
+template <class V8T, class T>
+class V8InterfaceBridge : public V8InterfaceBridgeBase {};
+
+}  // namespace bindings
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_INTERFACE_BRIDGE_H_
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index 6c25c30..170eeef 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -172,8 +172,9 @@
   // callbacks are missing and state gets out of sync.
   ThreadState* const thread_state = ThreadState::Current();
   thread_state->FinishIncrementalMarkingIfRunning(
-      BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kEagerSweeping, BlinkGC::GCReason::kThreadTerminationGC);
+      BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
+      BlinkGC::GCReason::kThreadTerminationGC);
   thread_state->DetachFromIsolate();
 }
 
diff --git a/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc b/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
index 21edc5f..ac42cd7 100644
--- a/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
+++ b/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
@@ -12,6 +12,46 @@
 
 namespace blink {
 
+namespace {
+
+struct WebInputEventDelete {
+  template <class EventType>
+  bool Execute(WebInputEvent* event) const {
+    if (!event)
+      return false;
+    DCHECK_EQ(sizeof(EventType), event->size());
+    delete static_cast<EventType*>(event);
+    return true;
+  }
+};
+
+template <typename Operator, typename ArgIn>
+bool Apply(Operator op, WebInputEvent::Type type, const ArgIn& arg_in) {
+  if (WebInputEvent::IsMouseEventType(type))
+    return op.template Execute<WebMouseEvent>(arg_in);
+  if (type == WebInputEvent::kMouseWheel)
+    return op.template Execute<WebMouseWheelEvent>(arg_in);
+  if (WebInputEvent::IsKeyboardEventType(type))
+    return op.template Execute<WebKeyboardEvent>(arg_in);
+  if (WebInputEvent::IsTouchEventType(type))
+    return op.template Execute<WebTouchEvent>(arg_in);
+  if (WebInputEvent::IsGestureEventType(type))
+    return op.template Execute<WebGestureEvent>(arg_in);
+  if (WebInputEvent::IsPointerEventType(type))
+    return op.template Execute<WebPointerEvent>(arg_in);
+
+  NOTREACHED() << "Unknown webkit event type " << type;
+  return false;
+}
+}
+
+void WebCoalescedInputEvent::WebInputEventDeleter::operator()(
+    WebInputEvent* event) const {
+  if (!event)
+    return;
+  Apply(WebInputEventDelete(), event->GetType(), event);
+}
+
 WebInputEvent* WebCoalescedInputEvent::EventPointer() {
   return event_.get();
 }
diff --git a/third_party/blink/renderer/platform/exported/web_url_error.cc b/third_party/blink/renderer/platform/exported/web_url_error.cc
index 9bc40c7..dde6ef5 100644
--- a/third_party/blink/renderer/platform/exported/web_url_error.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_error.cc
@@ -15,11 +15,13 @@
 
 WebURLError::WebURLError(int reason,
                          int extended_reason,
+                         net::ResolveErrorInfo resolve_error_info,
                          HasCopyInCache has_copy_in_cache,
                          IsWebSecurityViolation is_web_security_violation,
                          const WebURL& url)
     : reason_(reason),
       extended_reason_(extended_reason),
+      resolve_error_info_(resolve_error_info),
       has_copy_in_cache_(has_copy_in_cache == HasCopyInCache::kTrue),
       is_web_security_violation_(is_web_security_violation ==
                                  IsWebSecurityViolation::kTrue),
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
index 6414468..e34a9ccc 100644
--- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
+++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
@@ -199,9 +199,9 @@
   DCHECK(host_queue_->BelongsToCurrentThread());
   on_async_mutation_complete_ = std::move(done_callback);
   int next_async_mutation_id = GetNextAsyncMutationId();
-  TRACE_EVENT_ASYNC_BEGIN0("cc",
-                           "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
-                           next_async_mutation_id);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+      "cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+      TRACE_ID_LOCAL(next_async_mutation_id));
 
   CrossThreadOnceClosure on_done = CrossThreadBindOnce(
       [](scoped_refptr<base::SingleThreadTaskRunner> host_queue,
@@ -239,9 +239,9 @@
   }
   // The trace event deos not include queuing time. It covers the interval
   // between dispatching the request and retrieving the results.
-  TRACE_EVENT_ASYNC_END0("cc",
-                         "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
-                         async_mutation_id);
+  TRACE_EVENT_NESTABLE_ASYNC_END0(
+      "cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+      TRACE_ID_LOCAL(async_mutation_id));
   // The Async mutation duration is the total time between request and
   // completion, and thus includes queuing time.
   UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index 39bbc0d..1d1396c9 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -200,8 +200,8 @@
 
     ignorable_submitted_frames_.erase(pair.key);
 
-    TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
-        "media", "VideoFrameSubmitter", pair.key,
+    TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
+        "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(pair.key),
         pair.value->presentation_feedback->timestamp);
   }
 
@@ -539,10 +539,14 @@
   base::TimeTicks value;
   if (video_frame && video_frame->metadata()->GetTimeTicks(
                          media::VideoFrameMetadata::DECODE_END_TIME, &value)) {
-    TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0("media", "VideoFrameSubmitter",
-                                            *next_frame_token_, value);
-    TRACE_EVENT_ASYNC_STEP_PAST0("media", "VideoFrameSubmitter",
-                                 *next_frame_token_, "Pre-submit buffering");
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+        "media", "VideoFrameSubmitter", TRACE_ID_LOCAL(*next_frame_token_),
+        value);
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+        "media", "Pre-submit buffering", TRACE_ID_LOCAL(*next_frame_token_),
+        value);
+    TRACE_EVENT_NESTABLE_ASYNC_END0("media", "Pre-submit buffering",
+                                    TRACE_ID_LOCAL(*next_frame_token_));
 
     frame_token_to_timestamp_map_[*next_frame_token_] = value;
 
@@ -553,9 +557,9 @@
     UMA_HISTOGRAM_TIMES("Media.VideoFrameSubmitter.PreSubmitBuffering",
                         base::TimeTicks::Now() - value);
   } else {
-    TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
-        "media", "VideoFrameSubmitter", *next_frame_token_,
-        base::TimeTicks::Now(), "empty video frame?", !video_frame);
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("media", "VideoFrameSubmitter",
+                                      TRACE_ID_LOCAL(*next_frame_token_),
+                                      "empty video frame?", !video_frame);
   }
 
   // We don't assume that the ack is marked as having damage.  However, we're
diff --git a/third_party/blink/renderer/platform/heap/blink_gc.h b/third_party/blink/renderer/platform/heap/blink_gc.h
index a1ba0e5..495b759 100644
--- a/third_party/blink/renderer/platform/heap/blink_gc.h
+++ b/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -64,6 +64,11 @@
   STATIC_ONLY(BlinkGC);
 
  public:
+  // CollectionType represents generational collection. kMinor collects objects
+  // in the young generation (i.e. allocated since the previous collection
+  // cycle, since we use sticky bits), kMajor collects the entire heap.
+  enum class CollectionType { kMinor, kMajor };
+
   // When garbage collecting we need to know whether or not there
   // can be pointers to Blink GC managed objects on the stack for
   // each thread. When threads reach a safe point they record
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index b9bf108..0a552c9d 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -264,7 +264,8 @@
     ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted(
         BlinkGC::GCReason::kForcedGCForTesting);
     ThreadState::Current()->AtomicPauseMarkPrologue(
-        state, BlinkGC::kAtomicMarking, BlinkGC::GCReason::kPreciseGC);
+        BlinkGC::CollectionType::kMajor, state, BlinkGC::kAtomicMarking,
+        BlinkGC::GCReason::kPreciseGC);
   }
   ~TestGCScope() {
     ThreadState::Current()->AtomicPauseMarkEpilogue(BlinkGC::kAtomicMarking);
@@ -1827,8 +1828,8 @@
   for (int i = 0; i < 1000; i++)
     MakeGarbageCollected<SimpleFinalizedObject>();
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kConcurrentAndLazySweeping,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
       BlinkGC::GCReason::kForcedGCForTesting);
   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
   for (int i = 0; i < 10000; i++)
@@ -1861,8 +1862,8 @@
   for (int i = 0; i < 10; i++)
     MakeGarbageCollected<LargeHeapObject>();
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kConcurrentAndLazySweeping,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
       BlinkGC::GCReason::kForcedGCForTesting);
   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
   for (int i = 0; i < 10; i++) {
@@ -1873,8 +1874,8 @@
   MakeGarbageCollected<LargeHeapObject>();
   EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kConcurrentAndLazySweeping,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
       BlinkGC::GCReason::kForcedGCForTesting);
   EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
   PreciselyCollectGarbage();
diff --git a/third_party/blink/renderer/platform/heap/heap_test_utilities.cc b/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
index 3292be44..7370518 100644
--- a/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
@@ -15,7 +15,8 @@
 void TestSupportingGC::PreciselyCollectGarbage(
     BlinkGC::SweepingType sweeping_type) {
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, sweeping_type,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, sweeping_type,
       BlinkGC::GCReason::kForcedGCForTesting);
 }
 
@@ -23,7 +24,8 @@
 void TestSupportingGC::ConservativelyCollectGarbage(
     BlinkGC::SweepingType sweeping_type) {
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking, sweeping_type,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, sweeping_type,
       BlinkGC::GCReason::kForcedGCForTesting);
 }
 
diff --git a/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
index 80ef9b0..52d51d5 100644
--- a/third_party/blink/renderer/platform/heap/heap_thread_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -254,8 +254,9 @@
 
     // Step 4: Run a GC.
     ThreadState::Current()->CollectGarbage(
-        BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
-        BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting);
+        BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+        BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
+        BlinkGC::GCReason::kForcedGCForTesting);
     SwitchToMainThread();
   }
 
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index c3725ad1..4dfa4a49 100644
--- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -1536,8 +1536,9 @@
   driver.Start();
   driver.FinishSteps();
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kConcurrentAndLazySweeping, BlinkGC::GCReason::kConservativeGC);
+      BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
+      BlinkGC::GCReason::kConservativeGC);
 
   // Heap compaction should be canceled if incremental marking finishes with a
   // conservative GC.
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc
index 18d1115..fbc63e1 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -285,7 +285,8 @@
   DCHECK(!IsMainThread());
   DCHECK(CheckThread());
 
-  FinishIncrementalMarkingIfRunning(BlinkGC::kNoHeapPointersOnStack,
+  FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType::kMajor,
+                                    BlinkGC::kNoHeapPointersOnStack,
                                     BlinkGC::kIncrementalAndConcurrentMarking,
                                     BlinkGC::kConcurrentAndLazySweeping,
                                     BlinkGC::GCReason::kThreadTerminationGC);
@@ -306,7 +307,8 @@
   int current_count = GetPersistentRegion()->NodesInUse();
   DCHECK_GE(current_count, 0);
   while (current_count != old_count) {
-    CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+    CollectGarbage(BlinkGC::CollectionType::kMajor,
+                   BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
                    BlinkGC::kEagerSweeping,
                    BlinkGC::GCReason::kThreadTerminationGC);
     // Release the thread-local static persistents that were
@@ -325,7 +327,8 @@
          i < kMaxTerminationGCLoops && GetPersistentRegion()->NodesInUse();
          i++) {
       GetPersistentRegion()->PrepareForThreadStateTermination(this);
-      CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+      CollectGarbage(BlinkGC::CollectionType::kMajor,
+                     BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
                      BlinkGC::kEagerSweeping,
                      BlinkGC::GCReason::kThreadTerminationGC);
     }
@@ -697,7 +700,8 @@
       CollectAllGarbageForTesting();
       break;
     case kPreciseGCScheduled:
-      CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+      CollectGarbage(BlinkGC::CollectionType::kMajor,
+                     BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
                      BlinkGC::kConcurrentAndLazySweeping,
                      BlinkGC::GCReason::kPreciseGC);
       break;
@@ -706,9 +710,11 @@
   }
 }
 
-void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
-                                          BlinkGC::MarkingType marking_type,
-                                          BlinkGC::GCReason reason) {
+void ThreadState::AtomicPauseMarkPrologue(
+    BlinkGC::CollectionType collection_type,
+    BlinkGC::StackState stack_state,
+    BlinkGC::MarkingType marking_type,
+    BlinkGC::GCReason reason) {
   ThreadHeapStatsCollector::EnabledScope mark_prologue_scope(
       Heap().stats_collector(),
       ThreadHeapStatsCollector::kAtomicPauseMarkPrologue, "epoch", gc_age_,
@@ -744,7 +750,7 @@
     current_gc_data_.stack_state = stack_state;
     Heap().stats_collector()->UpdateReason(reason);
   } else {
-    MarkPhasePrologue(stack_state, marking_type, reason);
+    MarkPhasePrologue(collection_type, stack_state, marking_type, reason);
   }
 
   if (stack_state == BlinkGC::kNoHeapPointersOnStack) {
@@ -1158,7 +1164,8 @@
         BlinkGC::ToString(reason));
     AtomicPauseScope atomic_pause_scope(this);
     ScriptForbiddenScope script_forbidden_scope;
-    MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack,
+    MarkPhasePrologue(BlinkGC::CollectionType::kMajor,
+                      BlinkGC::kNoHeapPointersOnStack,
                       BlinkGC::kIncrementalAndConcurrentMarking, reason);
     {
       MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
@@ -1262,11 +1269,13 @@
   // UMA accounting and allow follow up GCs if necessary.
   DCHECK_EQ(BlinkGC::kIncrementalAndConcurrentMarking,
             current_gc_data_.marking_type);
-  CollectGarbage(BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type,
+  CollectGarbage(current_gc_data_.collection_type,
+                 BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type,
                  BlinkGC::kConcurrentAndLazySweeping, current_gc_data_.reason);
 }
 
 bool ThreadState::FinishIncrementalMarkingIfRunning(
+    BlinkGC::CollectionType collection_type,
     BlinkGC::StackState stack_state,
     BlinkGC::MarkingType marking_type,
     BlinkGC::SweepingType sweeping_type,
@@ -1278,14 +1287,16 @@
     if (IsUnifiedGCMarkingInProgress()) {
       unified_heap_controller()->FinalizeTracing();
     } else {
-      RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
+      RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type,
+                     reason);
     }
     return true;
   }
   return false;
 }
 
-void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
+void ThreadState::CollectGarbage(BlinkGC::CollectionType collection_type,
+                                 BlinkGC::StackState stack_state,
                                  BlinkGC::MarkingType marking_type,
                                  BlinkGC::SweepingType sweeping_type,
                                  BlinkGC::GCReason reason) {
@@ -1301,7 +1312,7 @@
       GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage);
 
   const bool was_incremental_marking = FinishIncrementalMarkingIfRunning(
-      stack_state, marking_type, sweeping_type, reason);
+      collection_type, stack_state, marking_type, sweeping_type, reason);
 
   // We don't want floating garbage for the specific garbage collection types
   // mentioned below. In this case we will follow up with a regular full
@@ -1315,7 +1326,8 @@
     CompleteSweep();
     SetGCState(kNoGCScheduled);
     Heap().stats_collector()->NotifyMarkingStarted(reason);
-    RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
+    RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type,
+                   reason);
   }
 
   const base::TimeDelta total_collect_garbage_time =
@@ -1569,7 +1581,8 @@
 }
 #endif  // ADDRESS_SANITIZER
 
-void ThreadState::RunAtomicPause(BlinkGC::StackState stack_state,
+void ThreadState::RunAtomicPause(BlinkGC::CollectionType collection_type,
+                                 BlinkGC::StackState stack_state,
                                  BlinkGC::MarkingType marking_type,
                                  BlinkGC::SweepingType sweeping_type,
                                  BlinkGC::GCReason reason) {
@@ -1578,7 +1591,7 @@
   TRACE_EVENT1("blink_gc,devtools.timeline", "BlinkGC.AtomicPhase", "forced",
                IsForcedGC(reason));
 
-  AtomicPauseMarkPrologue(stack_state, marking_type, reason);
+  AtomicPauseMarkPrologue(collection_type, stack_state, marking_type, reason);
   AtomicPauseMarkRoots(stack_state, marking_type, reason);
   AtomicPauseMarkTransitiveClosure();
   AtomicPauseMarkEpilogue(marking_type);
@@ -1595,7 +1608,8 @@
 
 }  // namespace
 
-void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
+void ThreadState::MarkPhasePrologue(BlinkGC::CollectionType collection_type,
+                                    BlinkGC::StackState stack_state,
                                     BlinkGC::MarkingType marking_type,
                                     BlinkGC::GCReason reason) {
   SetGCPhase(GCPhase::kMarking);
@@ -1608,6 +1622,7 @@
   }
 
   current_gc_data_.reason = reason;
+  current_gc_data_.collection_type = collection_type;
   current_gc_data_.visitor =
       IsUnifiedGCMarkingInProgress()
           ? std::make_unique<UnifiedHeapMarkingVisitor>(
@@ -1709,8 +1724,8 @@
   // We need to run multiple GCs to collect a chain of persistent handles.
   size_t previous_live_objects = 0;
   for (int i = 0; i < 5; ++i) {
-    CollectGarbage(stack_state, BlinkGC::kAtomicMarking,
-                   BlinkGC::kEagerSweeping,
+    CollectGarbage(BlinkGC::CollectionType::kMajor, stack_state,
+                   BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
                    BlinkGC::GCReason::kForcedGCForTesting);
     const size_t live_objects =
         Heap().stats_collector()->previous().marked_bytes;
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h
index 42b55d9..29db6e8 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.h
+++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -279,7 +279,8 @@
 
   void EnableCompactionForNextGCForTesting();
 
-  bool FinishIncrementalMarkingIfRunning(BlinkGC::StackState,
+  bool FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType,
+                                         BlinkGC::StackState,
                                          BlinkGC::MarkingType,
                                          BlinkGC::SweepingType,
                                          BlinkGC::GCReason);
@@ -335,7 +336,8 @@
   v8::Isolate* GetIsolate() const { return isolate_; }
 
   // Use CollectAllGarbageForTesting below for testing!
-  void CollectGarbage(BlinkGC::StackState,
+  void CollectGarbage(BlinkGC::CollectionType,
+                      BlinkGC::StackState,
                       BlinkGC::MarkingType,
                       BlinkGC::SweepingType,
                       BlinkGC::GCReason);
@@ -428,7 +430,8 @@
   // The following methods are used to compose RunAtomicPause. Public users
   // should use the CollectGarbage entrypoint. Internal users should use these
   // methods to compose a full garbage collection.
-  void AtomicPauseMarkPrologue(BlinkGC::StackState,
+  void AtomicPauseMarkPrologue(BlinkGC::CollectionType,
+                               BlinkGC::StackState,
                                BlinkGC::MarkingType,
                                BlinkGC::GCReason);
   void AtomicPauseMarkRoots(BlinkGC::StackState,
@@ -443,13 +446,15 @@
   // RunAtomicPause composes the final atomic pause that finishes a mark-compact
   // phase of a garbage collection. Depending on SweepingType it may also finish
   // sweeping or schedule lazy/concurrent sweeping.
-  void RunAtomicPause(BlinkGC::StackState,
+  void RunAtomicPause(BlinkGC::CollectionType,
+                      BlinkGC::StackState,
                       BlinkGC::MarkingType,
                       BlinkGC::SweepingType,
                       BlinkGC::GCReason);
 
   // The version is needed to be able to start incremental marking.
-  void MarkPhasePrologue(BlinkGC::StackState,
+  void MarkPhasePrologue(BlinkGC::CollectionType,
+                         BlinkGC::StackState,
                          BlinkGC::MarkingType,
                          BlinkGC::GCReason);
   void MarkPhaseEpilogue(BlinkGC::MarkingType);
@@ -587,6 +592,7 @@
   int gc_age_ = 0;
 
   struct GCData {
+    BlinkGC::CollectionType collection_type;
     BlinkGC::StackState stack_state;
     BlinkGC::MarkingType marking_type;
     BlinkGC::GCReason reason;
diff --git a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
index d618263..78c8242 100644
--- a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
+++ b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
@@ -46,7 +46,8 @@
 
   // Be conservative here as a new garbage collection gets started right away.
   thread_state_->FinishIncrementalMarkingIfRunning(
-      BlinkGC::kHeapPointersOnStack, BlinkGC::kIncrementalAndConcurrentMarking,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack,
+      BlinkGC::kIncrementalAndConcurrentMarking,
       BlinkGC::kConcurrentAndLazySweeping,
       thread_state_->current_gc_data_.reason);
 
@@ -65,7 +66,7 @@
   ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope(
       thread_state_->Heap().stats_collector());
   thread_state_->AtomicPauseMarkPrologue(
-      ToBlinkGCStackState(stack_state),
+      BlinkGC::CollectionType::kMajor, ToBlinkGCStackState(stack_state),
       BlinkGC::kIncrementalAndConcurrentMarking,
       thread_state_->current_gc_data_.reason);
   thread_state_->AtomicPauseMarkRoots(ToBlinkGCStackState(stack_state),
diff --git a/third_party/blink/renderer/platform/loader/fetch/DEPS b/third_party/blink/renderer/platform/loader/fetch/DEPS
index d430e11a..ed2faab5 100644
--- a/third_party/blink/renderer/platform/loader/fetch/DEPS
+++ b/third_party/blink/renderer/platform/loader/fetch/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+net/dns/public",
   "+services/network/public/cpp/fetch_api_utils.h",
 ]
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
index 8451bf1..9d9e7d7d 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -96,6 +96,7 @@
 ResourceError::ResourceError(const WebURLError& error)
     : error_code_(error.reason()),
       extended_error_code_(error.extended_reason()),
+      resolve_error_info_(error.resolve_error_info()),
       failing_url_(error.url()),
       is_access_check_(error.is_web_security_violation()),
       has_copy_in_cache_(error.has_copy_in_cache()),
@@ -108,6 +109,7 @@
   ResourceError error_copy(error_code_, failing_url_.Copy(),
                            cors_error_status_);
   error_copy.extended_error_code_ = extended_error_code_;
+  error_copy.resolve_error_info_ = resolve_error_info_;
   error_copy.has_copy_in_cache_ = has_copy_in_cache_;
   error_copy.localized_description_ = localized_description_.IsolatedCopy();
   error_copy.is_access_check_ = is_access_check_;
@@ -124,11 +126,11 @@
     return WebURLError(*cors_error_status_, has_copy_in_cache, failing_url_);
   }
 
-  return WebURLError(error_code_, extended_error_code_, has_copy_in_cache,
-                     is_access_check_
-                         ? WebURLError::IsWebSecurityViolation::kTrue
-                         : WebURLError::IsWebSecurityViolation::kFalse,
-                     failing_url_);
+  return WebURLError(
+      error_code_, extended_error_code_, resolve_error_info_, has_copy_in_cache,
+      is_access_check_ ? WebURLError::IsWebSecurityViolation::kTrue
+                       : WebURLError::IsWebSecurityViolation::kFalse,
+      failing_url_);
 }
 
 bool ResourceError::Compare(const ResourceError& a, const ResourceError& b) {
@@ -153,6 +155,9 @@
   if (a.extended_error_code_ != b.extended_error_code_)
     return false;
 
+  if (a.resolve_error_info_ != b.resolve_error_info_)
+    return false;
+
   return true;
 }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/third_party/blink/renderer/platform/loader/fetch/resource_error.h
index 592174ea..92ea2a2 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_error.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -29,6 +29,7 @@
 
 #include <iosfwd>
 #include "base/optional.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -99,6 +100,7 @@
 
   int error_code_;
   int extended_error_code_ = 0;
+  net::ResolveErrorInfo resolve_error_info_;
   KURL failing_url_;
   String localized_description_;
   bool is_access_check_ = false;
diff --git a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
index 86dcc94..870c3d2 100644
--- a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
+++ b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
@@ -253,7 +253,7 @@
 TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) {
   testing::InSequence s;
   wasp_impl_->Initialize(params_, &fake_callback_);
-  wasp_impl_->SetCopyAudioCallback(base::Bind(
+  wasp_impl_->SetCopyAudioCallback(WTF::BindRepeating(
       &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this)));
 
   const auto bus1 = media::AudioBus::Create(params_);
diff --git a/third_party/blink/renderer/platform/p2p/socket_client_impl.cc b/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
index 80b4899..eb40597 100644
--- a/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
+++ b/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
@@ -82,7 +82,7 @@
                                            const Vector<int8_t>& data,
                                            const rtc::PacketOptions& options,
                                            uint64_t packet_id) {
-  TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("p2p", "Send", packet_id);
 
   socket_->Send(data, network::P2PPacketInfo(address, options, packet_id),
                 net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
diff --git a/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc b/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
index 0413fe7..f6a029d 100644
--- a/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc
@@ -47,15 +47,17 @@
 }
 
 void CooperativeSchedulingManager::EnterAllowedStackScope() {
-  TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", "PreemptionAllowedStackScope",
-                           this);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("renderer.scheduler",
+                                    "PreemptionAllowedStackScope",
+                                    TRACE_ID_LOCAL(this));
 
   allowed_stack_scope_depth_++;
 }
 
 void CooperativeSchedulingManager::LeaveAllowedStackScope() {
-  TRACE_EVENT_ASYNC_END0("renderer.scheduler", "PreemptionAllowedStackScope",
-                         this);
+  TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+                                  "PreemptionAllowedStackScope",
+                                  TRACE_ID_LOCAL(this));
   allowed_stack_scope_depth_--;
   DCHECK_GE(allowed_stack_scope_depth_, 0);
 }
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc b/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
index 2324695..4f769b7a6 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
@@ -439,9 +439,15 @@
       !new_running_idle_task) {
     running_idle_task_for_tracing_ = false;
     if (!idle_period_deadline_.is_null() && now > idle_period_deadline_) {
-      TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
-          "renderer.scheduler", idle_period_tracing_name_, this,
-          "DeadlineOverrun",
+      if (last_sub_trace_event_name_) {
+        TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+                                        last_sub_trace_event_name_,
+                                        TRACE_ID_LOCAL(this));
+      }
+      last_sub_trace_event_name_ = "DeadlineOverrun";
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+          "renderer.scheduler", last_sub_trace_event_name_,
+          TRACE_ID_LOCAL(this),
           std::max(idle_period_deadline_, last_idle_task_trace_time_));
     }
   }
@@ -449,35 +455,46 @@
   if (IsInIdlePeriod(new_state)) {
     if (!idle_period_trace_event_started_) {
       idle_period_trace_event_started_ = true;
-      TRACE_EVENT_ASYNC_BEGIN1("renderer.scheduler", idle_period_tracing_name_,
-                               this, "idle_period_length_ms",
-                               (new_deadline - now).InMillisecondsF());
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+          "renderer.scheduler", idle_period_tracing_name_, TRACE_ID_LOCAL(this),
+          "idle_period_length_ms", (new_deadline - now).InMillisecondsF());
     }
 
+    const char* new_sub_trace_event_name = nullptr;
+
     if (new_running_idle_task) {
       last_idle_task_trace_time_ = now;
       running_idle_task_for_tracing_ = true;
-      TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
-                                   idle_period_tracing_name_, this,
-                                   "RunningIdleTask");
+      new_sub_trace_event_name = "RunningIdleTask";
     } else if (new_state == IdlePeriodState::kInShortIdlePeriod) {
-      TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
-                                   idle_period_tracing_name_, this,
-                                   "ShortIdlePeriod");
+      new_sub_trace_event_name = "ShortIdlePeriod";
     } else if (IsInLongIdlePeriod(new_state) &&
                new_state != IdlePeriodState::kInLongIdlePeriodPaused) {
-      TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
-                                   idle_period_tracing_name_, this,
-                                   "LongIdlePeriod");
+      new_sub_trace_event_name = "LongIdlePeriod";
     } else if (new_state == IdlePeriodState::kInLongIdlePeriodPaused) {
-      TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
-                                   idle_period_tracing_name_, this,
-                                   "LongIdlePeriodPaused");
+      new_sub_trace_event_name = "LongIdlePeriodPaused";
+    }
+
+    if (new_sub_trace_event_name) {
+      if (last_sub_trace_event_name_) {
+        TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+                                        last_sub_trace_event_name_,
+                                        TRACE_ID_LOCAL(this));
+      }
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+          "renderer.scheduler", new_sub_trace_event_name, TRACE_ID_LOCAL(this));
+      last_sub_trace_event_name_ = new_sub_trace_event_name;
     }
   } else if (idle_period_trace_event_started_) {
+    if (last_sub_trace_event_name_) {
+      TRACE_EVENT_NESTABLE_ASYNC_END0("renderer.scheduler",
+                                      last_sub_trace_event_name_,
+                                      TRACE_ID_LOCAL(this));
+      last_sub_trace_event_name_ = nullptr;
+    }
+    TRACE_EVENT_NESTABLE_ASYNC_END0(
+        "renderer.scheduler", idle_period_tracing_name_, TRACE_ID_LOCAL(this));
     idle_period_trace_event_started_ = false;
-    TRACE_EVENT_ASYNC_END0("renderer.scheduler", idle_period_tracing_name_,
-                           this);
   }
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
index aa80c6a..51c7593 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -195,6 +195,7 @@
     bool idle_period_trace_event_started_;
     bool running_idle_task_for_tracing_;
     const char* idle_period_tracing_name_;
+    const char* last_sub_trace_event_name_ = nullptr;
 
     DISALLOW_COPY_AND_ASSIGN(State);
   };
diff --git a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
index e957afa..d82b092 100644
--- a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
@@ -100,7 +100,7 @@
 
   ~StateTracer() {
     if (slice_is_open_)
-      TRACE_EVENT_ASYNC_END0(category, name_, object_);
+      TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_));
   }
 
   // String will be copied before leaving this function.
@@ -122,22 +122,19 @@
  private:
   void TraceImpl(const char* state, bool need_copy) {
     if (slice_is_open_) {
-      TRACE_EVENT_ASYNC_END0(category, name_, object_);
+      TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_));
       slice_is_open_ = false;
     }
     if (!state || !is_enabled())
       return;
 
-    // Trace viewer logic relies on subslice starting at the exact same time
-    // as the async event.
-    base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-    TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category, name_, object_, now);
     if (need_copy) {
-      TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category, name_, object_,
-                                                  TRACE_STR_COPY(state), now);
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category, name_,
+                                        TRACE_ID_LOCAL(object_), "state",
+                                        TRACE_STR_COPY(state));
     } else {
-      TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category, name_, object_,
-                                                  state, now);
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+          category, name_, TRACE_ID_LOCAL(object_), "state", state);
     }
     slice_is_open_ = true;
   }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 4f9da7ee..4efe837 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -640,9 +640,10 @@
   document_bound_weak_factory_.InvalidateWeakPtrs();
 
   for (const auto& it : back_forward_cache_opt_out_counts_) {
-    TRACE_EVENT_ASYNC_END0(
+    TRACE_EVENT_NESTABLE_ASYNC_END0(
         "renderer.scheduler", "ActiveSchedulerTrackedFeature",
-        reinterpret_cast<intptr_t>(this) ^ static_cast<int>(it.first));
+        TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+                       static_cast<int>(it.first)));
   }
 
   back_forward_cache_opt_out_counts_.clear();
@@ -665,10 +666,11 @@
 
   if (old_mask != new_mask) {
     NotifyDelegateAboutFeaturesAfterCurrentTask();
-    TRACE_EVENT_ASYNC_BEGIN1(
+    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
         "renderer.scheduler", "ActiveSchedulerTrackedFeature",
-        reinterpret_cast<intptr_t>(this) ^ static_cast<int>(feature), "feature",
-        FeatureToString(feature));
+        TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+                       static_cast<int>(feature)),
+        "feature", FeatureToString(feature));
   }
 }
 
@@ -686,9 +688,10 @@
 
   if (old_mask != new_mask) {
     NotifyDelegateAboutFeaturesAfterCurrentTask();
-    TRACE_EVENT_ASYNC_END0(
+    TRACE_EVENT_NESTABLE_ASYNC_END0(
         "renderer.scheduler", "ActiveSchedulerTrackedFeature",
-        reinterpret_cast<intptr_t>(this) ^ static_cast<int>(feature));
+        TRACE_ID_LOCAL(reinterpret_cast<intptr_t>(this) ^
+                       static_cast<int>(feature)));
   }
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index d75175c..072d1719 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -828,7 +828,7 @@
   // Note |virtual_time_domain_| is lazily created.
   std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_;
 
-  base::Closure update_policy_closure_;
+  base::RepeatingClosure update_policy_closure_;
   DeadlineTaskRunner delayed_update_policy_runner_;
   CancelableClosureHolder end_renderer_hidden_idle_period_closure_;
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index c44eecf..63d7ca8f 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -58,13 +58,10 @@
  public:
   explicit FakeInputEvent(blink::WebInputEvent::Type event_type,
                           int modifiers = WebInputEvent::kNoModifiers)
-      : WebInputEvent(event_type,
+      : WebInputEvent(sizeof(FakeInputEvent),
+                      event_type,
                       modifiers,
                       WebInputEvent::GetStaticTimeStampForTests()) {}
-
-  std::unique_ptr<WebInputEvent> Clone() const override {
-    return std::make_unique<FakeInputEvent>(*this);
-  }
 };
 
 class FakeTouchEvent : public blink::WebTouchEvent {
diff --git a/third_party/blink/renderer/platform/timer_test.cc b/third_party/blink/renderer/platform/timer_test.cc
index 0511f0f..942cc46 100644
--- a/third_party/blink/renderer/platform/timer_test.cc
+++ b/third_party/blink/renderer/platform/timer_test.cc
@@ -655,8 +655,8 @@
   owner = nullptr;
   // Explicit regular GC call to allow lazy sweeping.
   ThreadState::Current()->CollectGarbage(
-      BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
-      BlinkGC::kConcurrentAndLazySweeping,
+      BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
+      BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
       BlinkGC::GCReason::kForcedGCForTesting);
   // Since the heap is laziy swept, owner is not yet destructed.
   EXPECT_FALSE(record->OwnerIsDestructed());
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=OutOfBlinkCors b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
similarity index 72%
rename from third_party/blink/web_tests/FlagExpectations/enable-features=OutOfBlinkCors
rename to third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
index 8015ee0..835d10a 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-features=OutOfBlinkCors
+++ b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
@@ -3,30 +3,30 @@
 # tags: [ Release Debug ]
 # results: [ Timeout Crash Pass Failure Slow Skip ]
 
-# Tests that passes only with OOR-CORS, running at linux-oor-cors-rel bot.
-# Entries below are expected to revert relevant entries in NeverFixTests.
-# TODO(cbur.com/1001450): Remove this file after the OOR-CORS launch.
-crbug.com/870173 external/wpt/fetch/sec-metadata/appcache.tentative.https.sub.html [ Pass ]
-crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.html [ Pass ]
-crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.worker.html [ Pass ]
-crbug.com/870173 http/tests/devtools/console-xhr-logging.js [ Pass ]
-crbug.com/870173 http/tests/devtools/network/extra-info-redirects.js [ Pass ]
-crbug.com/870173 http/tests/eventsource/eventsource-cors-non-http.html [ Pass ]
-crbug.com/870173 http/tests/eventsource/workers/eventsource-cors-non-http.html [ Pass ]
-crbug.com/870173 http/tests/htmlimports/import-script-block-crossorigin-dynamic.html [ Pass ]
-crbug.com/870173 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js [ Pass ]
-crbug.com/870173 http/tests/preload/warning/request-mode.html [ Pass ]
-crbug.com/870173 http/tests/security/img-redirect-to-crossorigin-credentials.https.html [ Pass ]
-crbug.com/870173 http/tests/security/script-crossorigin-redirect-credentials.html [ Pass ]
-crbug.com/870173 http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Pass ]
-crbug.com/870173 http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Pass ]
-crbug.com/870173 mhtml/cid_in_html_resource.html [ Pass ]
-crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.html [ Pass ]
-crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.worker.html [ Pass ]
-crbug.com/870173 virtual/omt-worker-fetch/http/tests/workers/worker-redirect.html [ Pass ]
+# Tests that passes only with OOR-CORS.
+# These tests should not pass at linux-blink-cors-rel fyi bot.
+# TODO(cbur.com/1001450): Remove this file after removing the OOR-CORS releted
+# enterprise policies.
+crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.html [ Skip ]
+crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.worker.html [ Skip ]
+crbug.com/870173 http/tests/devtools/console-xhr-logging.js [ Skip ]
+crbug.com/870173 http/tests/devtools/network/extra-info-redirects.js [ Skip ]
+crbug.com/870173 http/tests/eventsource/eventsource-cors-non-http.html [ Skip ]
+crbug.com/870173 http/tests/eventsource/workers/eventsource-cors-non-http.html [ Skip ]
+crbug.com/870173 http/tests/htmlimports/import-script-block-crossorigin-dynamic.html [ Skip ]
+crbug.com/870173 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js [ Skip ]
+crbug.com/870173 http/tests/preload/warning/request-mode.html [ Skip ]
+crbug.com/870173 http/tests/security/img-redirect-to-crossorigin-credentials.https.html [ Skip ]
+crbug.com/870173 http/tests/security/script-crossorigin-redirect-credentials.html [ Skip ]
+crbug.com/870173 http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Skip ]
+crbug.com/870173 http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Skip ]
+crbug.com/870173 mhtml/cid_in_html_resource.html [ Skip ]
+crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.html [ Skip ]
+crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.worker.html [ Skip ]
+crbug.com/870173 virtual/omt-worker-fetch/http/tests/workers/worker-redirect.html [ Skip ]
 
 # The fetch-request-xhr.https.html fails on some checks, but has an expectation
-# file to ignore text diffs. It also fails on the same checks even with
+# file to ignore text diffs. It also fails on the same checks even without
 # OOR-CORS, but with different texts. Just mark them as Failure.
 crbug.com/870173 external/wpt/service-workers/service-worker/fetch-request-xhr.https.html [ Failure ]
 crbug.com/870173 virtual/cache-storage-eager-reading/external/wpt/service-workers/service-worker/fetch-request-xhr.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer b/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer
index 14751d0..efbe44e 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer
+++ b/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer
@@ -7,3 +7,4 @@
 crbug.com/1002522 fast/canvas/canvas-toDataURL-webp.html [ Skip ]
 
 crbug.com/1027772 media/video-controls-visibility-multimodal-mouse-after-touch.html [ Failure Pass ]
+crbug.com/1027772 [ Win10 ] media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
index 412dee5..da692e2 100644
--- a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
+++ b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
@@ -71,13 +71,13 @@
 crbug.com/626703 external/wpt/acid/acid3/test.html [ Pass ]
 crbug.com/986282 external/wpt/client-hints/accept-ch-lifetime.tentative.https.html [ Crash Pass ]
 crbug.com/982194 external/wpt/css/CSS2/floats-clear/float-non-replaced-height-001.xht [ Failure ]
-crbug.com/982194 external/wpt/css/CSS2/floats-clear/floats-149.xht [ Failure ]
+crbug.com/982194 external/wpt/css/CSS2/floats-clear/floats-149.xht [ Failure Pass ]
 crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht [ Failure ]
 crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht [ Failure ]
 crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht [ Failure ]
 crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ]
 crbug.com/982194 external/wpt/css/CSS2/floats/hit-test-floats-001.html [ Failure ]
-crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash ]
+crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash Failure ]
 crbug.com/982194 external/wpt/css/CSS2/positioning/toogle-abspos-on-relpos-inline-child.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Pass ]
@@ -85,7 +85,7 @@
 crbug.com/982194 external/wpt/css/css-overflow/overflow-inline-transform-relative.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-position/position-absolute-in-inline-002.html [ Failure ]
 crbug.com/984438 external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Failure ]
-crbug.com/982194 external/wpt/css/css-sizing/orthogonal-writing-mode-float-in-inline.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-sizing/orthogonal-writing-mode-float-in-inline.html [ Failure Pass ]
 crbug.com/982194 external/wpt/css/css-text-decor/text-decoration-color.html [ Pass ]
 crbug.com/949909 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ]
 crbug.com/949909 external/wpt/css/css-text-decor/text-emphasis-position-above-left-001.xht [ Failure ]
@@ -119,7 +119,6 @@
 crbug.com/982194 external/wpt/css/cssom-view/elementsFromPoint-inline-vrl-rtl.html [ Failure ]
 crbug.com/982194 external/wpt/css/cssom-view/elementsFromPoint-simple.html [ Failure ]
 crbug.com/982194 external/wpt/css/cssom-view/offsetTopLeft-trailing-space-inline.html [ Failure ]
-crbug.com/982194 external/wpt/css/cssom-view/scrollIntoView-svg-shape.html [ Failure Pass ]
 crbug.com/982194 external/wpt/css/csui/text-overflow-002.html [ Failure ]
 crbug.com/982194 external/wpt/css/filter-effects/filtered-inline-applies-to-float.html [ Failure ]
 crbug.com/982194 external/wpt/css/filter-effects/filtered-inline-is-container.html [ Failure ]
@@ -189,7 +188,6 @@
 crbug.com/928838 external/wpt/html/user-activation/activation-transfer-with-click.tentative.html [ Failure ]
 crbug.com/626703 external/wpt/infrastructure/testdriver/actions/eventOrder.html [ Timeout ]
 crbug.com/982194 external/wpt/intersection-observe/v2/scaled-target.html [ Failure ]
-crbug.com/982194 external/wpt/intersection-observer/root-margin.html [ Failure Pass ]
 crbug.com/982194 external/wpt/intersection-observer/v2/drop-shadow-filter-vertical-rl.html [ Failure ]
 crbug.com/982194 external/wpt/intersection-observer/v2/inline-occlusion.html [ Failure ]
 crbug.com/982194 external/wpt/largest-contentful-paint/larger-text.html [ Timeout ]
@@ -203,10 +201,6 @@
 crbug.com/982194 external/wpt/pointerevents/extension/pointerevent_touch-action-pan-right-css_touch.html [ Timeout ]
 crbug.com/982194 external/wpt/pointerevents/extension/pointerevent_touch-action-pan-up-css_touch.html [ Timeout ]
 crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch.html [ Pass Timeout ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-pan-x-css_touch.html [ Failure Pass ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html [ Pass Timeout ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-span-none-test_touch.html [ Failure Pass ]
 crbug.com/626703 external/wpt/screen-orientation/onchange-event.html [ Timeout ]
 crbug.com/626703 external/wpt/screen-orientation/orientation-reading.html [ Timeout ]
 crbug.com/982194 external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ]
@@ -229,23 +223,18 @@
 crbug.com/982194 fast/block/float/float-in-float-hit-testing.html [ Failure ]
 crbug.com/982194 fast/block/float/overhanging-float-container-add-compositing.html [ Failure ]
 crbug.com/982194 fast/block/float/relative-painted-twice.html [ Failure ]
-crbug.com/982194 fast/block/positioning/absolute-in-inline-dynamic.html [ Failure ]
+crbug.com/982194 fast/block/positioning/absolute-in-inline-dynamic.html [ Failure Pass ]
 crbug.com/982194 fast/block/positioning/hittest-on-relative-positioned-children.html [ Failure ]
 crbug.com/982194 fast/block/positioning/rel-positioned-inline-changes-width.html [ Failure ]
-crbug.com/982194 fast/block/positioning/relative-overflow-replaced.html [ Failure Pass ]
-crbug.com/982194 fast/borders/rtl-border-01.html [ Failure Pass ]
-crbug.com/982194 fast/borders/rtl-border-02.html [ Failure Pass ]
-crbug.com/982194 fast/borders/rtl-border-03.html [ Failure Pass ]
 crbug.com/982194 fast/css-generated-content/table-parts-before-and-after.html [ Failure ]
 crbug.com/982194 fast/css/area-computedStyle.html [ Timeout ]
 crbug.com/982194 fast/css/first-line-hover-001.html [ Failure ]
 crbug.com/982194 fast/css/getComputedStyle/computed-style-percentage-top-with-position-inline.html [ Failure ]
 crbug.com/982194 fast/css/hover-active-quirks.html [ Failure ]
-crbug.com/982194 fast/css/invalidation-errors-2.html [ Failure ]
-crbug.com/982194 fast/css/invalidation-errors.html [ Failure ]
+crbug.com/982194 fast/css/invalidation-errors-2.html [ Failure Pass ]
+crbug.com/982194 fast/css/invalidation-errors.html [ Failure Pass ]
 crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ]
 crbug.com/982194 fast/css/pseudo-element-hit-test.html [ Crash ]
-crbug.com/982194 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Failure Pass ]
 crbug.com/982194 fast/css/unknown-pseudo-element-matching.html [ Failure ]
 crbug.com/982194 fast/dnd/link-dragging-draggable-div-with-dragged-link.html [ Timeout ]
 crbug.com/982194 fast/dnd/link-dragging-draggable-div-with-link.html [ Timeout ]
@@ -299,11 +288,10 @@
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/982194 fast/events/touch/gesture/gesture-tap-mouse-events-between-frames.html [ Failure ]
 crbug.com/982194 fast/events/touch/gesture/gesture-tap-mouse-events.html [ Failure ]
-crbug.com/874695 fast/forms/color/color-suggestion-picker-one-row-appearance.html [ Pass ]
-crbug.com/874695 fast/forms/color/color-suggestion-picker-two-row-appearance.html [ Pass ]
+crbug.com/874695 fast/forms/color/color-suggestion-picker-one-row-appearance.html [ Failure Pass ]
+crbug.com/874695 fast/forms/color/color-suggestion-picker-two-row-appearance.html [ Failure Pass ]
 crbug.com/982194 fast/forms/focus-selection-input.html [ Failure ]
 crbug.com/982194 fast/forms/focus-selection-textarea.html [ Failure ]
-crbug.com/982194 fast/forms/huge-mac-input-clamped-width.html [ Failure Pass ]
 crbug.com/982194 fast/forms/label/label-click.html [ Failure ]
 crbug.com/982194 fast/forms/label/label-selection-by-dragging.html [ Failure ]
 crbug.com/982194 fast/forms/label/label-selection-by-textSelection-and-click.html [ Failure ]
@@ -321,15 +309,9 @@
 crbug.com/982194 fast/multicol/span/vertical-lr.html [ Pass ]
 crbug.com/982194 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Pass ]
 crbug.com/982194 fast/multicol/vertical-lr/nested-columns.html [ Pass ]
-crbug.com/982194 fast/overflow/scroll-div-hide-show.html [ Failure Pass ]
 crbug.com/982194 fast/replaced/absolute-position-percentage-height.html [ Failure ]
 crbug.com/814953 fast/replaced/no-focus-ring-iframe.html [ Failure ]
-crbug.com/986018 fast/scroll-snap/snaps-for-different-key-granularity.html [ Failure Pass ]
-crbug.com/982194 fast/scrolling/scrollable-area-frame-overflow-hidden.html [ Failure Pass ]
-crbug.com/982194 fast/scrolling/scrollable-area-frame-overried-inherited-visibility-hidden.html [ Failure Pass ]
-crbug.com/982194 fast/scrolling/scrollable-area-frame-scrolling-yes.html [ Failure Pass ]
-crbug.com/982194 fast/scrolling/scrollable-area-frame-visibility-hidden-child.html [ Failure Pass ]
-crbug.com/982194 fast/scrolling/scrollable-area-frame.html [ Failure Pass ]
+crbug.com/986018 fast/scroll-snap/snaps-for-different-key-granularity.html [ Pass ]
 crbug.com/889952 fast/selectors/selection-window-inactive.html [ Pass ]
 crbug.com/591099 fast/selectors/shadow-host-div-with-span.html [ Failure ]
 crbug.com/591099 fast/selectors/shadow-host-div-with-text.html [ Failure ]
@@ -368,10 +350,10 @@
 crbug.com/451577 crbug.com/924308 http/tests/devtools/console/console-format-es6-2.js [ Crash Failure Pass Timeout ]
 crbug.com/451577 crbug.com/916975 http/tests/devtools/console/console-repeat-count.js [ Crash Failure Pass Timeout ]
 crbug.com/451577 http/tests/devtools/console/console-search.js [ Pass ]
-crbug.com/967526 http/tests/devtools/console/console-uncaught-promise.js [ Failure Pass ]
+crbug.com/967526 http/tests/devtools/console/console-uncaught-promise.js [ Pass ]
 crbug.com/982194 http/tests/devtools/coverage/decorations-after-script-formatter.js [ Pass Timeout ]
 crbug.com/678482 http/tests/devtools/debugger/fetch-breakpoints.js [ Pass Timeout ]
-crbug.com/846997 http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Pass Timeout ]
+crbug.com/846997 http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Timeout ]
 crbug.com/850358 http/tests/devtools/editor/text-editor-enter-behaviour.js [ Pass Timeout ]
 crbug.com/846982 crbug.com/874695 http/tests/devtools/editor/text-editor-formatter.js [ Crash Pass Timeout ]
 crbug.com/420008 crbug.com/749738 http/tests/devtools/editor/text-editor-word-jumps.js [ Crash Pass Timeout ]
@@ -386,7 +368,7 @@
 crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-3/style-autocomplete.js [ Crash Pass Timeout ]
 crbug.com/938884 http/tests/devtools/elements/styles-3/styles-add-blank-property.js [ Pass Timeout ]
 crbug.com/945665 http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Failure Timeout ]
-crbug.com/945665 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Failure Timeout ]
+crbug.com/945665 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Timeout ]
 crbug.com/945665 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Failure ]
 crbug.com/945665 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure ]
 crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-3/styles-variables.js [ Crash Pass Timeout ]
@@ -394,7 +376,7 @@
 crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-4/styles-keyframes.js [ Crash Pass Timeout ]
 crbug.com/946714 http/tests/devtools/elements/styles-4/styles-live-locations-leak.js [ Timeout ]
 crbug.com/982116 http/tests/devtools/elements/styles-4/styles-new-API.js [ Pass Timeout ]
-crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass Timeout ]
+crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Timeout ]
 crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-4/undo-add-new-rule.js [ Crash Pass Timeout ]
 crbug.com/978304 http/tests/devtools/elements/styles-4/undo-add-property.js [ Pass Timeout ]
 crbug.com/982194 http/tests/devtools/elements/styles/styles-mouse-test.js [ Failure ]
@@ -426,7 +408,7 @@
 crbug.com/874695 http/tests/devtools/sources/debugger/debugger-proto-property.js [ Pass ]
 crbug.com/874695 http/tests/devtools/sxg/sxg-cert-not-found.js [ Pass ]
 crbug.com/874695 http/tests/devtools/sxg/sxg-disable-cache.js [ Pass ]
-crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Failure Pass ]
+crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass ]
 crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch.js [ Pass ]
 crbug.com/420008 crbug.com/916975 http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Crash Failure Pass Timeout ]
 crbug.com/982194 http/tests/input/discard-events-to-unstable-iframe.html [ Failure ]
@@ -438,37 +420,34 @@
 crbug.com/982194 http/tests/navigation/ping-cross-origin-from-https.html [ Timeout ]
 crbug.com/982194 http/tests/navigation/ping-cross-origin.html [ Timeout ]
 crbug.com/982194 http/tests/navigation/ping-same-origin.html [ Timeout ]
-crbug.com/874695 http/tests/permissions/chromium/test-request-worker.html [ Pass Timeout ]
+crbug.com/874695 http/tests/permissions/chromium/test-request-worker.html [ Pass ]
 crbug.com/982194 http/tests/security/anchor-download-allow-blob.html [ Timeout ]
 crbug.com/982194 http/tests/security/anchor-download-allow-data.html [ Timeout ]
 crbug.com/982194 http/tests/security/anchor-download-allow-sameorigin.html [ Timeout ]
 crbug.com/982194 http/tests/security/contentSecurityPolicy/frame-src-vs-shift-click.html [ Timeout ]
 crbug.com/982194 http/tests/security/mixedContent/insecure-css-resources.html [ Failure Pass ]
-crbug.com/982194 images/55.html [ Failure ]
+crbug.com/982194 images/55.html [ Failure Pass ]
 crbug.com/24182 images/png-suite/test.html [ Pass ]
 crbug.com/982194 inspector-protocol/accessibility/accessibility-getFullAXTree-display-locked.js [ Failure ]
 crbug.com/982194 inspector-protocol/accessibility/accessibility-getFullAXTree.js [ Failure ]
 crbug.com/874695 crbug.com/936165 media/autoplay-muted.html [ Crash Pass Timeout ]
 crbug.com/908347 media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
 crbug.com/942951 media/controls/controls-layout-in-different-size.html [ Pass ]
-crbug.com/982194 media/picture-in-picture/v2/detached-iframe.html [ Failure Pass Timeout ]
+crbug.com/982194 media/picture-in-picture/v2/detached-iframe.html [ Failure Timeout ]
 crbug.com/982194 media/picture-in-picture/v2/request-picture-in-picture-twice.html [ Failure ]
 crbug.com/982194 media/picture-in-picture/v2/request-picture-in-picture.html [ Failure Timeout ]
 crbug.com/874695 media/remoteplayback/prompt-twice-throws.html [ Pass ]
-crbug.com/982194 overflow/overflow-inline-002.html [ Failure Pass ]
-crbug.com/982194 overflow/overflow-inline-003.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/background/background-misaligned.html [ Failure ]
 crbug.com/982194 paint/invalidation/block-layout-inline-children-replaced.html [ Failure ]
 crbug.com/982194 paint/invalidation/block-no-inflow-children.html [ Failure ]
-crbug.com/982194 paint/invalidation/box/hover-pseudo-borders.html [ Crash Failure ]
+crbug.com/982194 paint/invalidation/box/hover-pseudo-borders.html [ Failure ]
 crbug.com/982194 paint/invalidation/box/invalidate-box-shadow-currentColor.html [ Failure ]
 crbug.com/982194 paint/invalidation/bugzilla-3509.html [ Failure ]
 crbug.com/982194 paint/invalidation/bugzilla-5699.html [ Failure ]
 crbug.com/982194 paint/invalidation/bugzilla-6278.html [ Failure ]
 crbug.com/982194 paint/invalidation/bugzilla-7235.html [ Failure ]
-crbug.com/982194 paint/invalidation/clip/subtree-root-clip-2.html [ Failure ]
+crbug.com/982194 paint/invalidation/clip/subtree-root-clip-2.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ]
-crbug.com/982194 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer.html [ Failure ]
 crbug.com/982194 paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer.html [ Failure ]
 crbug.com/982194 paint/invalidation/compositing/text-color-change.html [ Failure ]
@@ -530,8 +509,6 @@
 crbug.com/982194 paint/invalidation/remove-inline-after-layout.html [ Failure ]
 crbug.com/982194 paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ]
 crbug.com/982194 paint/invalidation/repaint-descandant-on-ancestor-layer-move.html [ Failure ]
-crbug.com/982194 paint/invalidation/repaint-overlay/layers-overlay.html [ Failure Pass ]
-crbug.com/982194 paint/invalidation/scroll/caret-with-composited-scroll.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/scroll/inline-style-change-in-scrolled-view.html [ Failure ]
 crbug.com/982194 paint/invalidation/scroll/invalidate-after-composited-scroll-of-window.html [ Failure ]
 crbug.com/982194 paint/invalidation/scroll/layout-state-scrolloffset.html [ Failure ]
@@ -556,10 +533,6 @@
 crbug.com/982194 paint/invalidation/selection/text-selection-rect-in-overflow.html [ Failure ]
 crbug.com/982194 paint/invalidation/stacked-diacritics.html [ Failure ]
 crbug.com/982194 paint/invalidation/svg/absolute-sized-content-with-resources.xhtml [ Failure ]
-crbug.com/982194 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure Pass ]
-crbug.com/982194 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure Pass ]
-crbug.com/982194 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure Pass ]
-crbug.com/982194 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/svg/object-sizing-no-width-height-change-content-box-size.xhtml [ Failure ]
 crbug.com/982194 paint/invalidation/svg/relative-sized-content-with-resources.xhtml [ Failure ]
 crbug.com/982194 paint/invalidation/svg/relative-sized-content.xhtml [ Failure ]
@@ -573,7 +546,6 @@
 crbug.com/982194 paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem.html [ Failure ]
 crbug.com/982194 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ]
 crbug.com/982194 paint/invalidation/svg/svg-image-change-content-size.xhtml [ Failure ]
-crbug.com/982194 paint/invalidation/svg/text-xy-updates-SVGList.xhtml [ Failure Pass ]
 crbug.com/982194 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ]
 crbug.com/982194 paint/invalidation/table/cached-change-cell-sl-border-color.html [ Failure ]
 crbug.com/982194 paint/invalidation/table/collapsed-border-current-color.html [ Crash ]
@@ -590,12 +562,7 @@
 crbug.com/919789 paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos.html [ Failure ]
 crbug.com/919789 paint/invalidation/window-resize/window-resize-vertical-writing-mode.html [ Failure ]
 crbug.com/676229 plugins/mouse-click-plugin-clears-selection.html [ Failure ]
-crbug.com/982194 printing/return-from-printing-mode.html [ Failure Pass ]
-crbug.com/982194 svg/overflow/overflow-on-outermost-svg-element-horizontal-auto.svg [ Failure Pass ]
-crbug.com/982194 svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults.xhtml [ Failure Pass ]
-crbug.com/982194 svg/transforms/transformed-text-fill-pattern.html [ Failure Pass ]
-crbug.com/982194 tables/mozilla/bugs/bug26553.html [ Failure ]
-crbug.com/982194 tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure Pass ]
+crbug.com/982194 tables/mozilla/bugs/bug26553.html [ Failure Pass ]
 crbug.com/982194 touchadjustment/disabled-formelements.html [ Failure ]
 crbug.com/982194 touchadjustment/html-label.html [ Failure ]
 crbug.com/982194 touchadjustment/stylus-generated-gesture-tap.html [ Failure ]
@@ -605,22 +572,17 @@
 crbug.com/718155 virtual/android/fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
 crbug.com/982194 virtual/audio-service/http/tests/media/video-frame-size-change.html [ Failure Pass ]
 crbug.com/874695 crbug.com/936165 virtual/audio-service/media/autoplay-muted.html [ Crash Pass Timeout ]
-crbug.com/982194 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure Timeout ]
-crbug.com/908347 virtual/audio-service/media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
-crbug.com/942951 virtual/audio-service/media/controls/controls-layout-in-different-size.html [ Pass ]
-crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/detached-iframe.html [ Failure Pass ]
-crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/request-picture-in-picture-twice.html [ Failure ]
-crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/request-picture-in-picture.html [ Failure Pass ]
-crbug.com/874695 virtual/audio-service/media/remoteplayback/prompt-twice-throws.html [ Pass ]
-crbug.com/982194 virtual/audio-service/media/stable/video-object-fit-stable.html [ Pass ]
-crbug.com/982194 virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/udate-bytecheck.https.html [ Timeout ]
-virtual/composite-after-paint/compositing/geometry/outline-change.html [ Pass ]
-virtual/composite-after-paint/compositing/gestures/gesture-tapHighlight-img.html [ Pass ]
-
+crbug.com/982194 accessibility/dimensions-include-descendants.html [ Failure ]
 crbug.com/982194 accessibility/selection-affinity.html [ Failure ]
+crbug.com/982194 compositing/gestures/gesture-tapHighlight-img-and-text.html [ Failure ]
+crbug.com/982194 compositing/gestures/gesture-tapHighlight-img.html [ Failure ]
 crbug.com/982194 compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ]
 crbug.com/982194 css3/filters/backdrop-filter-svg.html [ Pass ]
+crbug.com/982194 css3/selectors3/xml/css3-modsel-64.xml [ Failure Pass ]
+crbug.com/982194 css3/tab-size-complex-path.html [ Failure ]
 crbug.com/982194 custom-elements/form-submission-file.html [ Crash Pass ]
+crbug.com/982194 custom-elements/form-validation-bubble-appearance.html [ Failure ]
+crbug.com/982194 editing/selection/extend-to-line-boundary.html [ Failure ]
 crbug.com/982194 external/wpt/compat/webkit-text-fill-color-property-005.html [ Pass ]
 crbug.com/982194 external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html [ Failure ]
 crbug.com/982194 external/wpt/css/CSS2/floats/float-nowrap-7.html [ Pass ]
@@ -637,6 +599,7 @@
 crbug.com/982194 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-break/avoid-border-break.html [ Pass ]
+crbug.com/982194 external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht [ Pass ]
 crbug.com/982194 external/wpt/css/css-color/t425-hsla-onscreen-b.xht [ Pass ]
 crbug.com/982194 external/wpt/css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht [ Pass ]
@@ -723,7 +686,7 @@
 crbug.com/982194 external/wpt/css/css-lists/li-value-reversed-004.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-lists/li-value-reversed-005.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-lists/list-item-definition.html [ Pass ]
-crbug.com/982194 external/wpt/css/css-lists/list-style-type-string-003.html [ Failure Pass ]
+crbug.com/982194 external/wpt/css/css-lists/list-style-type-string-003.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-lists/list-style-type-string-005b.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-lists/list-style-type-string-007.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-masking/clip-path-svg-content/clip-path-recursion-002.svg [ Pass ]
@@ -799,6 +762,10 @@
 crbug.com/982194 external/wpt/css/css-pseudo/marker-list-style-position.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-pseudo/spelling-error-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html [ Pass ]
+crbug.com/982194 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-001.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-002.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-003.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-004.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-sizing/clone-intrinsic-size.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-002.html [ Pass ]
@@ -831,6 +798,22 @@
 crbug.com/982194 external/wpt/css/css-text/hyphens/hyphens-out-of-flow-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/hyphens/hyphens-span-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/hyphens/shy-styling-001.html [ Pass ]
+crbug.com/982194 external/wpt/css/css-text/i18n/ja/css-text-line-break-ja-in-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/ja/css-text-line-break-ja-pr-normal.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/ja/css-text-line-break-ja-pr-strict.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/other-lang/css-text-line-break-de-in-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/other-lang/css-text-line-break-de-pr-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/other-lang/css-text-line-break-de-pr-normal.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/other-lang/css-text-line-break-de-pr-strict.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-cj-strict.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-in-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-iteration-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-pr-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-pr-normal.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/unknown-lang/css-text-line-break-pr-strict.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-in-loose.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-pr-normal.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-pr-strict.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-text/letter-spacing/letter-spacing-bidi-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/letter-spacing/letter-spacing-bidi-002.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/letter-spacing/letter-spacing-control-chars-001.html [ Pass ]
@@ -843,6 +826,8 @@
 crbug.com/982194 external/wpt/css/css-text/overflow-wrap/overflow-wrap-anywhere-inline-002.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/overflow-wrap/overflow-wrap-normal-keep-all-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/tab-size/tab-size-spacing-001.html [ Pass ]
+crbug.com/982194 external/wpt/css/css-text/tab-size/tab-size.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-text/text-align/text-align-last-empty-inline.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-text/text-indent/text-indent-tab-positions-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/text-transform/math/text-transform-math-auto-002.tentative.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-text/text-transform/math/text-transform-math-bold-script-001.tentative.html [ Pass ]
@@ -905,12 +890,31 @@
 crbug.com/982194 external/wpt/css/css-writing-modes/direction-upright-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/mongolian-orientation-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/mongolian-orientation-002.html [ Pass ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001a.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001b.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001c.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001d.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001e.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001f.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001g.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001h.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001i.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001j.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001k.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001l.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001m.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001n.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001o.html [ Failure ]
+crbug.com/982194 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001p.html [ Failure ]
 crbug.com/982194 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-013.xht [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/sizing-orthog-vlr-in-htb-008.xht [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-008.xht [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/text-combine-upright-value-all-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/text-combine-upright-value-all-002.html [ Pass ]
 crbug.com/982194 external/wpt/css/css-writing-modes/text-combine-upright-value-all-003.html [ Pass ]
+crbug.com/982194 external/wpt/css/cssom-view/elementFromPoint-mixed-font-sizes.html [ Failure ]
+crbug.com/982194 external/wpt/css/cssom-view/getBoundingClientRect-empty-inline.html [ Failure ]
+crbug.com/982194 external/wpt/css/cssom-view/getClientRects-inline-inline-child.html [ Failure ]
 crbug.com/982194 external/wpt/css/filter-effects/css-filters-animation-combined-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/mediaqueries/viewport-script-dynamic.html [ Pass ]
 crbug.com/982194 external/wpt/css/motion/offset-path-ray-009.html [ Pass ]
@@ -927,6 +931,22 @@
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-content-rtl-002.html [ Pass ]
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-content-vertWM-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-content-vertWM-002.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-001.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-002.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-003.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-004.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-005.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-006.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-007.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-008.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-rtl-001.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-rtl-002.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-rtl-003.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-rtl-004.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-vertWM-001.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-vertWM-002.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-vertWM-003.html [ Pass ]
+crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-align-self-vertWM-004.html [ Pass ]
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-fallback-align-content-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-justify-content-001.html [ Pass ]
 crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-justify-content-002.html [ Pass ]
@@ -1044,7 +1064,14 @@
 crbug.com/982194 external/wpt/encoding/eof-utf-8-three.html [ Pass ]
 crbug.com/982194 external/wpt/encoding/eof-utf-8-two.html [ Pass ]
 crbug.com/982194 external/wpt/fetch/metadata/download.tentative.https.sub.html [ Failure ]
+crbug.com/982194 external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-06.html [ Pass ]
+crbug.com/982194 external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-08.html [ Pass ]
+crbug.com/982194 external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-10.html [ Pass ]
+crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-05.html [ Pass ]
+crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-14.html [ Pass ]
+crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-17.html [ Pass ]
 crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-19.html [ Failure ]
+crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-23.html [ Pass ]
 crbug.com/982194 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ]
 crbug.com/982194 external/wpt/html/rendering/non-replaced-elements/tables/table-border-1.html [ Pass ]
 crbug.com/982194 external/wpt/html/rendering/non-replaced-elements/tables/table-border-3q.html [ Failure ]
@@ -1068,11 +1095,13 @@
 crbug.com/982194 external/wpt/html/user-activation/activation-hierarchy-parent-manual.sub.tentative.html [ Timeout ]
 crbug.com/982194 external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Pass Timeout ]
 crbug.com/982194 external/wpt/infrastructure/assumptions/blank.html [ Pass ]
+crbug.com/982194 external/wpt/infrastructure/assumptions/document-fonts-ready.html [ Failure ]
 crbug.com/982194 external/wpt/infrastructure/reftest/legacy/reftest_fuzzy_chain_ini.html [ Pass ]
 crbug.com/982194 external/wpt/infrastructure/reftest/reftest_fuzzy_1.html [ Pass ]
 crbug.com/982194 external/wpt/infrastructure/reftest/reftest_fuzzy_ini_full.html [ Pass ]
 crbug.com/982194 external/wpt/infrastructure/reftest/reftest_fuzzy_ini_ref_only.html [ Pass ]
 crbug.com/982194 external/wpt/infrastructure/reftest/reftest_fuzzy_ini_short.html [ Pass ]
+crbug.com/982194 external/wpt/intersection-observer/inline-client-rect.html [ Failure ]
 crbug.com/982194 external/wpt/intersection-observer/v2/blur-filter.html [ Failure ]
 crbug.com/982194 external/wpt/intersection-observer/v2/delay-test.html [ Failure Pass ]
 crbug.com/982194 external/wpt/largest-contentful-paint/element-only-when-fully-active.html [ Timeout ]
@@ -1151,8 +1180,8 @@
 crbug.com/982194 external/wpt/native-file-system/sandboxed_FileSystemBaseHandle-postMessage.tentative.https.window.html [ Pass Timeout ]
 crbug.com/982194 external/wpt/payment-method-basic-card/apply_the_modifiers.html [ Timeout ]
 crbug.com/982194 external/wpt/payment-method-basic-card/steps_for_selecting_the_payment_handler.html [ Timeout ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch.html [ Failure Pass ]
-crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch.html [ Failure Pass ]
+crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch.html [ Pass Timeout ]
+crbug.com/982194 external/wpt/pointerevents/pointerevent_touch-action-span-none-test_touch.html [ Timeout ]
 crbug.com/982194 external/wpt/quirks/percentage-height-quirk-excludes-flex-grid-001.html [ Pass ]
 crbug.com/982194 external/wpt/quirks/text-decoration-doesnt-propagate-into-tables/quirks.html [ Pass ]
 crbug.com/982194 external/wpt/screen-orientation/onchange-event-subframe.html [ Pass ]
@@ -1168,6 +1197,7 @@
 crbug.com/982194 external/wpt/trusted-types/eval-csp-no-tt.tentative.html [ Failure ]
 crbug.com/982194 external/wpt/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html [ Failure ]
 crbug.com/982194 external/wpt/trusted-types/eval-no-csp-no-tt.tentative.html [ Failure ]
+crbug.com/982194 external/wpt/uievents/click/click_event_target_child_parent.html [ Timeout ]
 crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Pass ]
 crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Pass ]
 crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_tracks.html [ Pass ]
@@ -1364,11 +1394,27 @@
 crbug.com/982194 fast/block/float/hittest-float-in-anchor.html [ Failure ]
 crbug.com/982194 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Pass ]
 crbug.com/982194 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
+crbug.com/982194 fast/borders/outline-alpha-inline.html [ Failure ]
+crbug.com/982194 fast/canvas/canvas-measure-bidi-text.html [ Failure ]
 crbug.com/982194 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Pass ]
+crbug.com/982194 fast/dom/Element/client-rect-list-argument.html [ Failure ]
+crbug.com/982194 fast/dom/Element/getBoundingClientRect.html [ Failure ]
+crbug.com/982194 fast/dom/Element/getClientRects.html [ Failure ]
+crbug.com/982194 fast/dom/Range/getClientRects.html [ Failure ]
+crbug.com/982194 fast/dom/Range/range-spanning-elements-bounding-client-rect.html [ Failure ]
 crbug.com/982194 fast/dom/SelectorAPI/resig-SelectorsAPI-test.xhtml [ Pass ]
+crbug.com/982194 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Pass Timeout ]
+crbug.com/982194 fast/dom/shadow/gesture-tapHighlight-shadow-tree.html [ Failure ]
 crbug.com/982194 fast/events/mouse-relative-position.html [ Failure ]
 crbug.com/982194 fast/events/tabindex-focus-blur-all.html [ Pass ]
 crbug.com/982194 fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
+crbug.com/982194 fast/events/touch/gesture/gesture-tap-result.html [ Failure ]
+crbug.com/982194 fast/inline/br-client-rect.html [ Failure ]
+crbug.com/982194 fast/inline/continuation-outlines-with-layers.html [ Failure ]
+crbug.com/982194 fast/inline/continuation-outlines.html [ Failure ]
+crbug.com/982194 fast/loader/document-with-fragment-url-1.html [ Timeout ]
+crbug.com/982194 fast/loader/document-with-fragment-url-3.html [ Timeout ]
+crbug.com/982194 fast/loader/document-with-fragment-url-4.html [ Timeout ]
 crbug.com/982194 fast/multicol/vertical-lr/column-break-with-balancing.html [ Failure ]
 crbug.com/982194 fast/multicol/vertical-lr/column-count-with-rules.html [ Failure ]
 crbug.com/982194 fast/multicol/vertical-lr/column-rules.html [ Failure ]
@@ -1382,15 +1428,58 @@
 crbug.com/982194 fast/multicol/vertical-rl/nested-columns.html [ Pass ]
 crbug.com/982194 fast/overflow/scrollbar-click-retains-focus.html [ Failure ]
 crbug.com/982194 fast/scroll-snap/snaps-after-scrollbar-scrolling.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-big-box-border-radius-001.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html [ Crash Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-ellipse-margin-left.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-ellipse-margin-right.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-image-margin-001.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-image-margin-002.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-left.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-right.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-rounded-boxes-001.html [ Failure ]
+crbug.com/982194 fast/shapes/shape-outside-floats/shape-outside-rounded-boxes-002.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-1st-stop.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-container-only-white-space.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-container-white-space.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-date.html [ Failure ]
 crbug.com/982194 fast/spatial-navigation/snav-expandable-sub-menu.html [ Failure ]
 crbug.com/982194 fast/spatial-navigation/snav-first-fragment-offscreen.html [ Failure ]
 crbug.com/982194 fast/spatial-navigation/snav-first-rtl-fragment-offscreen.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-focus-rect-contains-links.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-fragmented-link-partially-offscreen.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-fully-aligned-vertically.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-iframe-no-focusable-content.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-input.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-keyboard-scrollers-search-origin-bug.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-more-aligned-at-top.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-multiple-select.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-navigate-visible-elements-only2.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-offscreen-content.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-radio-group.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-radio.html [ Failure ]
 crbug.com/982194 fast/spatial-navigation/snav-search-focused-scroller-first.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-single-select-list.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-single-select.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-skippable-candidate.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-table-traversal.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-textarea.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-two-elements-one-line.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-unit-overflow-and-scroll-in-direction.html [ Failure ]
+crbug.com/982194 fast/spatial-navigation/snav-use-visual-viewport.html [ Failure ]
+crbug.com/982194 fast/sub-pixel/size-of-span-with-different-positions.html [ Failure ]
+crbug.com/982194 fast/sub-pixel/width-of-inline-in-float.html [ Failure ]
+crbug.com/982194 fast/writing-mode/flipped-blocks-text-map-local-to-container.html [ Failure ]
 crbug.com/982194 fragmentation/repeating-thead-under-repeating-thead.html [ Pass ]
+crbug.com/982194 hittesting/border-hittest-inlineFlowBox.html [ Failure ]
+crbug.com/982194 hittesting/culled-inline.html [ Failure ]
+crbug.com/982194 http/tests/css/css-image-valued-shape.html [ Failure ]
 crbug.com/982194 http/tests/devtools/application-panel/storage-view-reports-quota.js [ Pass Timeout ]
+crbug.com/982194 http/tests/devtools/console/console-prompt-keyboard.js [ Failure ]
+crbug.com/982194 http/tests/devtools/editor/text-editor-accessibility.js [ Failure ]
 crbug.com/982194 http/tests/devtools/elements/edit/edit-dom-actions-2.js [ Pass Timeout ]
 crbug.com/982194 http/tests/devtools/elements/highlight/highlight-dom-updates.js [ Pass Timeout ]
-crbug.com/982194 http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Failure Timeout ]
+crbug.com/982194 http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js [ Failure ]
+crbug.com/982194 http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Timeout ]
 crbug.com/982194 http/tests/devtools/indexeddb/database-refresh-view.js [ Pass ]
 crbug.com/982194 http/tests/devtools/oopif/oopif-storage.js [ Pass ]
 crbug.com/982194 http/tests/devtools/profiler/heap-snapshot-location.js [ Pass ]
@@ -1406,8 +1495,12 @@
 crbug.com/982194 http/tests/devtools/service-workers/user-agent-override.js [ Pass ]
 crbug.com/982194 http/tests/devtools/sources/debugger/navigator-view.js [ Crash Pass ]
 crbug.com/982194 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Pass ]
-crbug.com/982194 http/tests/navigation/anchor-frames-same-origin.html [ Failure Pass ]
+crbug.com/982194 http/tests/history/client-redirect-after-push-state.html [ Failure Pass ]
+crbug.com/982194 http/tests/navigation/anchor-frames-same-origin.html [ Failure ]
 crbug.com/982194 ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ Failure ]
+crbug.com/982194 inspector-protocol/dom-snapshot/dom-snapshot-captureSnapshot-pseudo-element.js [ Failure ]
+crbug.com/982194 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ]
+crbug.com/982194 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ]
 crbug.com/982194 jquery/attributes.html [ Pass ]
 crbug.com/982194 jquery/core.html [ Pass ]
 crbug.com/982194 jquery/css.html [ Pass ]
@@ -1417,24 +1510,35 @@
 crbug.com/982194 jquery/manipulation.html [ Pass Timeout ]
 crbug.com/982194 jquery/offset.html [ Pass ]
 crbug.com/982194 jquery/traversing.html [ Pass ]
-crbug.com/982194 media/video-canvas-draw.html [ Failure Pass ]
+crbug.com/982194 media/video-canvas-draw.html [ Failure ]
+crbug.com/982194 paint/inline/outline-offset.html [ Failure ]
 crbug.com/982194 paint/invalidation/compositing/float-under-composited-inline.html [ Failure ]
 crbug.com/982194 paint/invalidation/flexbox/scrollbars-changed.html [ Failure ]
 crbug.com/982194 paint/invalidation/multi-layout-one-frame.html [ Failure ]
 crbug.com/982194 paint/invalidation/position/absolute-position-moved.html [ Failure ]
-crbug.com/982194 paint/invalidation/svg/color-stop-properties.html [ Failure Pass ]
 crbug.com/982194 paint/invalidation/svg/scroll-hit-test.xhtml [ Failure ]
 crbug.com/982194 svg/custom/visibility-enable-on-svg-element-contained-border-radius.html [ Failure ]
 crbug.com/982194 svg/custom/visibility-enable-on-svg-element-contained-viewport-size.html [ Failure ]
 crbug.com/982194 svg/custom/visibility-enable-on-svg-element.html [ Failure ]
+crbug.com/982194 touchadjustment/event-triggered-widgets.html [ Failure ]
+crbug.com/982194 touchadjustment/touch-links-active.html [ Failure ]
 crbug.com/982194 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ]
+crbug.com/908347 virtual/audio-service/media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
+crbug.com/942951 virtual/audio-service/media/controls/controls-layout-in-different-size.html [ Pass ]
+crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/detached-iframe.html [ Failure Pass ]
+crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/request-picture-in-picture-twice.html [ Failure ]
+crbug.com/982194 virtual/audio-service/media/picture-in-picture/v2/request-picture-in-picture.html [ Failure Pass ]
+crbug.com/874695 virtual/audio-service/media/remoteplayback/prompt-twice-throws.html [ Pass ]
+crbug.com/982194 virtual/audio-service/media/stable/video-object-fit-stable.html [ Pass ]
 crbug.com/982194 virtual/audio-service/media/video-canvas-draw.html [ Failure ]
+crbug.com/982194 virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/udate-bytecheck.https.html [ Timeout ]
+crbug.com/982194 virtual/composite-after-paint/compositing/gestures/gesture-tapHighlight-img.html [ Failure ]
 crbug.com/982194 virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/file/file-appearance-basic.html [ Failure ]
 crbug.com/982194 virtual/controls-refresh/color-scheme/file/file-appearance-basic.html [ Failure ]
-crbug.com/982194 virtual/exotic-color-space/images/55.html [ Failure ]
+crbug.com/982194 virtual/exotic-color-space/images/55.html [ Failure Pass ]
 crbug.com/982194 virtual/exotic-color-space/images/yuv-decode-eligible/color-profile-layer-filter.html [ Failure ]
-crbug.com/985520 virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-enter-from-interest-a11y.html [ Pass ]
-crbug.com/985520 virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-enter-from-interest.html [ Pass ]
+crbug.com/985520 virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-enter-from-interest-a11y.html [ Failure Pass ]
+crbug.com/985520 virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-enter-from-interest.html [ Failure Pass ]
 crbug.com/982194 virtual/forced-high-contrast-cascade/external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-01.html [ Failure ]
 crbug.com/982194 virtual/forced-high-contrast-cascade/external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-02.html [ Failure ]
 crbug.com/982194 virtual/forced-high-contrast-cascade/external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-03.html [ Failure ]
@@ -1449,20 +1553,27 @@
 crbug.com/982194 virtual/forced-high-contrast-colors/external/wpt/forced-colors-mode/backplate/forced-colors-mode-backplate-09.html [ Failure ]
 crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/focus-selection-input.html [ Failure ]
 crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/focus-selection-textarea.html [ Failure ]
-crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/huge-mac-input-clamped-width.html [ Failure Pass ]
 crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/label/label-click.html [ Failure ]
 crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/label/label-selection-by-dragging.html [ Failure ]
 crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/label/label-selection-by-textSelection-and-click.html [ Failure ]
-crbug.com/982194 virtual/gpu-rasterization/images/55.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/date-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/month-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/time-suggestion-picker-appearance-rtl.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/week-suggestion-picker-appearance-rtl.html [ Failure ]
+crbug.com/982194 virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/week-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
+crbug.com/982194 virtual/gpu-rasterization/images/55.html [ Failure Pass ]
 crbug.com/956736 virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map.html [ Pass ]
 crbug.com/982194 virtual/gpu/fast/canvas/OffscreenCanvas-zero-size-readback.html [ Crash ]
 crbug.com/982194 virtual/gpu/fast/canvas/canvas-arc-circumference.html [ Pass ]
 crbug.com/982194 virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill.html [ Pass ]
 crbug.com/982194 virtual/gpu/fast/canvas/canvas-ellipse-circumference.html [ Pass ]
+crbug.com/982194 virtual/gpu/fast/canvas/canvas-measure-bidi-text.html [ Failure ]
 crbug.com/866850 virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Failure Pass ]
 crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/fieldset-001.html [ Pass ]
 crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/floats-and-text-narrow-and-short-dynamic.html [ Pass ]
-crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/line-after-unbreakable-float-after-padding.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ]
+crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/line-after-unbreakable-float-after-padding.html [ Pass Timeout ]
 crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/widows-orphans-001.html [ Pass ]
 crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/widows-orphans-002.html [ Pass ]
 crbug.com/982194 virtual/layout_ng_block_frag/external/wpt/css/css-break/widows-orphans-003.html [ Pass ]
@@ -1671,7 +1782,7 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/float-edge.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/float-paginate.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/nested-columns.html [ Pass ]
-crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/unsplittable-inline-block.html [ Crash Failure ]
+crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/unsplittable-inline-block.html [ Failure ]
 crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/abspos-auto-position-on-line.html [ Pass ]
 crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/column-break-with-balancing.html [ Failure ]
 crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Pass ]
@@ -1732,8 +1843,56 @@
 crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Pass ]
 crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/hittest-overlapping-margin.html [ Failure ]
 crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/negative-margins-001.html [ Pass ]
-crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/overflow-top-left.html [ Failure Pass ]
 crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/ttwf-reftest-flex-inline.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001b.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-001-block.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-004.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-align-self-baseline-horiz-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-horiz-001a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-horiz-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-horiz-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-horiz-002.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-vert-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-vert-002.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-single-item-001a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-single-item-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-baseline-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-column-row-gap-004.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-004a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001a.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001b.xhtml [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002c.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002a.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002c.html [ Pass ]
+crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-paint-ordering-002.xhtml [ Pass ]
 crbug.com/982194 virtual/lazyload-image/http/tests/lazyload/style-dimension.html [ Pass ]
 crbug.com/982194 virtual/mouseevent_fractional/fast/events/autoscroll-should-not-stop-on-keypress.html [ Failure ]
 crbug.com/779170 virtual/mouseevent_fractional/fast/events/clientXY-in-zoom-and-scroll.html [ Pass ]
@@ -1761,6 +1920,7 @@
 crbug.com/874695 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-click.html [ Pass ]
 crbug.com/982194 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-tap-mouse-events-between-frames.html [ Failure ]
 crbug.com/982194 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-tap-mouse-events.html [ Failure ]
+crbug.com/982194 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-tap-result.html [ Failure ]
 crbug.com/874695 virtual/mouseevent_fractional/fast/events/touch/touch-slider-no-js-touch-listener.html [ Pass ]
 crbug.com/779170 virtual/mouseevent_fractional/fast/events/zoom-dblclick.html [ Failure ]
 crbug.com/982194 virtual/not-site-per-process/http/tests/devtools/debugger/fetch-breakpoints.js [ Pass Timeout ]
@@ -1815,29 +1975,30 @@
 crbug.com/982194 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/982194 virtual/scroll_customization/fast/events/touch/gesture/gesture-tap-mouse-events-between-frames.html [ Failure ]
 crbug.com/982194 virtual/scroll_customization/fast/events/touch/gesture/gesture-tap-mouse-events.html [ Failure ]
-crbug.com/982194 virtual/scroll_customization/fast/scrolling/scrollable-area-frame-overflow-hidden.html [ Failure Pass ]
-crbug.com/982194 virtual/scroll_customization/fast/scrolling/scrollable-area-frame-overried-inherited-visibility-hidden.html [ Failure Pass ]
-crbug.com/982194 virtual/scroll_customization/fast/scrolling/scrollable-area-frame-scrolling-yes.html [ Failure Pass ]
-crbug.com/982194 virtual/scroll_customization/fast/scrolling/scrollable-area-frame-visibility-hidden-child.html [ Failure Pass ]
-crbug.com/982194 virtual/scroll_customization/fast/scrolling/scrollable-area-frame.html [ Failure Pass ]
+crbug.com/982194 virtual/scroll_customization/fast/events/touch/gesture/gesture-tap-result.html [ Failure ]
 crbug.com/982194 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html [ Pass ]
-crbug.com/982194 virtual/stable/http/tests/navigation/anchor-frames-same-origin.html [ Failure Pass ]
+crbug.com/982194 virtual/stable/http/tests/navigation/anchor-frames-same-origin.html [ Failure ]
 crbug.com/982194 virtual/stable/http/tests/navigation/ping-cookie.html [ Timeout ]
 crbug.com/982194 virtual/stable/http/tests/navigation/ping-cross-origin-from-https.html [ Timeout ]
 crbug.com/982194 virtual/stable/http/tests/navigation/ping-cross-origin.html [ Timeout ]
 crbug.com/982194 virtual/stable/http/tests/navigation/ping-same-origin.html [ Timeout ]
-crbug.com/982194 virtual/stable/media/stable/video-object-fit-stable.html [ Failure Pass ]
+crbug.com/982194 virtual/stable/media/stable/video-object-fit-stable.html [ Pass ]
+crbug.com/982194 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html [ Pass ]
+crbug.com/982194 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/css-module/import-css-module-basic.html [ Pass ]
+crbug.com/982194 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/css-module/utf8.tentative.html [ Pass ]
 crbug.com/874695 virtual/sxg-with-network-service/http/tests/devtools/sxg/sxg-disable-cache.js [ Pass ]
 crbug.com/851363 virtual/sxg-with-network-service/http/tests/devtools/sxg/sxg-prefetch-fail.js [ Failure Pass ]
 crbug.com/851363 virtual/sxg-with-network-service/http/tests/devtools/sxg/sxg-prefetch.js [ Failure Pass ]
+crbug.com/982194 virtual/text-antialias/font-fallback-synthetic-italics.html [ Failure ]
 crbug.com/982194 virtual/text-antialias/font-format-support-color-cff2-vertical.html [ Pass ]
+crbug.com/982194 virtual/text-antialias/font-ligature-letter-spacing.html [ Failure ]
+crbug.com/982194 virtual/text-antialias/font-variant-width.html [ Failure ]
+crbug.com/982194 virtual/text-antialias/international/listbox-width-rtl.html [ Failure ]
+crbug.com/982194 virtual/text-antialias/international/shape-across-elements.html [ Failure ]
 crbug.com/982194 virtual/text-antialias/remove-zero-length-run.html [ Failure ]
+crbug.com/982194 virtual/text-antialias/sub-pixel/text-scaling-pixel.html [ Failure ]
+crbug.com/982194 virtual/text-antialias/tab-min-size.html [ Failure ]
 crbug.com/982194 virtual/threaded-no-composited-antialiasing/animations/timing/animation-duration-infinite.html [ Failure Pass ]
-crbug.com/982194 virtual/threaded-prefer-compositing/fast/scrolling/scrollable-area-frame-overflow-hidden.html [ Failure Pass ]
-crbug.com/982194 virtual/threaded-prefer-compositing/fast/scrolling/scrollable-area-frame-overried-inherited-visibility-hidden.html [ Failure Pass ]
-crbug.com/982194 virtual/threaded-prefer-compositing/fast/scrolling/scrollable-area-frame-scrolling-yes.html [ Failure Pass ]
-crbug.com/982194 virtual/threaded-prefer-compositing/fast/scrolling/scrollable-area-frame-visibility-hidden-child.html [ Failure Pass ]
-crbug.com/982194 virtual/threaded-prefer-compositing/fast/scrolling/scrollable-area-frame.html [ Failure Pass ]
 crbug.com/982194 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/lazyload-disabled-tentative.sub.html [ Failure ]
 crbug.com/982194 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/lazyload-enabled-tentative.sub.html [ Pass ]
 crbug.com/982194 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/loading-frame-default-eager-disabled-tentative.sub.html [ Pass ]
@@ -1847,7 +2008,6 @@
 crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Pass ]
 crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass ]
 crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-worker-events.js [ Failure Pass ]
-crbug.com/982194 virtual/threaded/printing/return-from-printing-mode.html [ Failure Pass ]
 crbug.com/982194 virtual/unified-autoplay/external/wpt/feature-policy/experimental-features/lazyload/lazyload-enabled-tentative.sub.html [ Pass ]
 crbug.com/982194 virtual/unified-autoplay/external/wpt/feature-policy/experimental-features/lazyload/loading-frame-default-eager-disabled-tentative.sub.html [ Pass ]
 crbug.com/982194 virtual/web-components-v0-disabled/external/wpt/html/semantics/scripting-1/the-script-element/css-module/utf8.tentative.html [ Pass ]
@@ -1861,6 +2021,11 @@
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Document/CaretRangeFromPoint/hittest-empty-line.html [ Failure ]
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Document/CaretRangeFromPoint/hittest-outside-image.html [ Failure ]
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Document/CaretRangeFromPoint/replace-element.html [ Failure ]
+crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Element/client-rect-list-argument.html [ Failure ]
+crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Element/getBoundingClientRect.html [ Failure ]
+crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Element/getClientRects.html [ Failure ]
+crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Range/getClientRects.html [ Failure ]
+crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/Range/range-spanning-elements-bounding-client-rect.html [ Failure ]
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/elementsFromPoint/elementsFromPoint-inline.html [ Failure ]
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/elementsFromPoint/elementsFromPoint-simple.html [ Failure ]
 crbug.com/982194 virtual/web-components-v0-disabled/fast/dom/nodesFromRect/nodesFromRect-child-frame-content.html [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 758d9b8..1dd36f1 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2085,29 +2085,6 @@
 external/wpt/uievents/order-of-events/mouse-events/wheel-scrolling-manual.html [ Skip ]
 external/wpt/html/webappapis/user-prompts/print-manual.html [ Skip ]
 
-# Tests that do not pass with the Blink CORS, but pass with OOR-CORS.
-# We maintain the Blink CORS for a while, and keep it work without regressions.
-# But will not change the existing behavior for Blink CORS when expectations are
-# changed for the spec update, other features side-effects, and so on.
-# TODO(cbur.com/870173): Double check following failed tests later.
-crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.html [ Skip ]
-crbug.com/870173 external/wpt/resource-timing/cors-preflight.any.worker.html [ Skip ]
-crbug.com/870173 http/tests/devtools/console-xhr-logging.js [ Skip ]
-crbug.com/870173 http/tests/devtools/network/extra-info-redirects.js [ Skip ]
-crbug.com/870173 http/tests/eventsource/eventsource-cors-non-http.html [ Skip ]
-crbug.com/870173 http/tests/eventsource/workers/eventsource-cors-non-http.html [ Skip ]
-crbug.com/870173 http/tests/htmlimports/import-script-block-crossorigin-dynamic.html [ Skip ]
-crbug.com/870173 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js [ Skip ]
-crbug.com/870173 http/tests/preload/warning/request-mode.html [ Skip ]
-crbug.com/870173 http/tests/security/img-redirect-to-crossorigin-credentials.https.html [ Skip ]
-crbug.com/870173 http/tests/security/script-crossorigin-redirect-credentials.html [ Skip ]
-crbug.com/870173 http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Skip ]
-crbug.com/870173 http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Skip ]
-crbug.com/870173 mhtml/cid_in_html_resource.html [ Skip ]
-crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.html [ Skip ]
-crbug.com/870173 virtual/omt-worker-fetch/external/wpt/resource-timing/cors-preflight.any.worker.html [ Skip ]
-crbug.com/870173 virtual/omt-worker-fetch/http/tests/workers/worker-redirect.html [ Skip ]
-
 # Windows doesn't have native overlay scrollbar
 [ Win ] virtual/overlay-scrollbar/* [ Skip ]
 
diff --git a/third_party/blink/web_tests/README b/third_party/blink/web_tests/README
deleted file mode 100644
index b1511f95..0000000
--- a/third_party/blink/web_tests/README
+++ /dev/null
@@ -1,8 +0,0 @@
-This folder is for Chrome-specific tests only. Tests that should work across
-browsers should be placed in third_party/blink/web_tests/external/wpt.
-
-For more information about blink tests in general, please see:
-https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_tests.md
-
-For more information about web platform tests, please see:
-https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_platform_tests.md
diff --git a/third_party/blink/web_tests/README.md b/third_party/blink/web_tests/README.md
new file mode 100644
index 0000000..ee0fa39
--- /dev/null
+++ b/third_party/blink/web_tests/README.md
@@ -0,0 +1,3 @@
+The documentation for this directory is at:
+- [Web Tests](/docs/testing/web_tests.md)
+- [Writing Web Tests](/docs/testing/writing_web_tests.md)
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 8515c993..5fff69c 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -826,7 +826,7 @@
 crbug.com/591099 [ Fuchsia ] virtual/text-antialias/international/bidi-LDB-2-formatting-characters.html [ Failure ]
 crbug.com/591099 [ Fuchsia ] virtual/text-antialias/international/bidi-neutral-directionality-paragraph-start.html [ Failure ]
 crbug.com/591099 [ Fuchsia ] fast/writing-mode/english-lr-text.html [ Failure ]
-#crbug.com/591099 [ Fuchsia ] tables/mozilla/bugs/bug2479-3.html [ Failure Timeout ]
+crbug.com/591099 [ Fuchsia ] tables/mozilla/bugs/bug2479-3.html [ Failure Timeout ]
 crbug.com/591099 [ Fuchsia ] tables/mozilla/bugs/bug2479-4.html [ Failure ]
 crbug.com/591099 [ Fuchsia ] tables/mozilla/bugs/bug59354.html [ Failure Timeout ]
 crbug.com/591099 [ Fuchsia ] tables/mozilla/bugs/bug7342.html [ Failure ]
@@ -1447,7 +1447,6 @@
 crbug.com/1003506 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/percentage-heights-007.html [ Failure ]
 crbug.com/1025630 [ Mac ] virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/select-element-zero-height-001.html [ Failure ]
 crbug.com/1025630 [ Mac ] virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/select-element-zero-height-002.html [ Failure ]
-crbug.com/1035582 [ Linux ] virtual/layout_ng_flex_box/css3/flexbox/button.html [ Failure Pass ]
 
 # Fieldset in NG
 #
@@ -1783,25 +1782,6 @@
 # ======
 # From this point until the end of the Form Controls Refresh section, these are
 # in-progress rebaselines, tracked at crbug.com/1035582.
-crbug.com/1035582 compositing/contents-opaque/control-layer.html [ Failure Pass ]
-crbug.com/1035582 css3/selectors3/html/css3-modsel-19b.html [ Failure Pass ]
-crbug.com/1035582 css3/selectors3/xhtml/css3-modsel-19b.xml [ Failure Pass ]
-crbug.com/1035582 css3/selectors3/xml/css3-modsel-19b.xml [ Failure Pass ]
-crbug.com/1035582 editing/pasteboard/input-field-1.html [ Failure Pass ]
-crbug.com/1035582 editing/pasteboard/pasting-tabs.html [ Failure Pass ]
-crbug.com/1035582 editing/selection/replaced-boundaries-3.html [ Failure Pass ]
-crbug.com/1035582 editing/selection/select-box.html [ Failure Pass ]
-crbug.com/1035582 editing/selection/select-element-paragraph-boundary.html [ Failure Pass ]
-crbug.com/1035582 fast/block/float/float-avoidance.html [ Failure Pass ]
-crbug.com/1035582 fast/block/margin-collapse/103.html [ Failure Pass ]
-crbug.com/1035582 fast/css/continuationCrash.html [ Failure Pass ]
-crbug.com/1035582 fast/css/margin-top-bottom-dynamic.html [ Failure Pass ]
-crbug.com/1035582 fast/css/text-overflow-input.html [ Failure Pass ]
-crbug.com/1035582 fast/dom/HTMLMeterElement/meter-boundary-values.html [ Failure Pass ]
-crbug.com/1035582 fast/dom/HTMLMeterElement/meter-clone.html [ Failure Pass ]
-crbug.com/1035582 fast/dom/HTMLMeterElement/meter-element-markup.html [ Failure Pass ]
-crbug.com/1035582 fast/dom/HTMLMeterElement/meter-optimums.html [ Failure Pass ]
-crbug.com/1035582 fast/dom/HTMLMeterElement/meter-styles.html [ Failure Pass ]
 crbug.com/1035582 fast/forms/basic-buttons.html [ Failure Pass ]
 crbug.com/1035582 fast/forms/basic-inputs.html [ Failure Pass ]
 crbug.com/1035582 fast/forms/button/button-align.html [ Failure Pass ]
@@ -1935,50 +1915,12 @@
 crbug.com/1035582 fast/forms/week-multiple-fields/week-multiple-fields-spinbutton-change-and-input-events.html [ Failure Pass ]
 crbug.com/1035582 fast/forms/week-multiple-fields/week-multiple-fields-wheel-event.html [ Failure Pass ]
 crbug.com/1035582 fast/forms/week/week-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 fast/parser/document-write-option.html [ Failure Pass ]
-crbug.com/1035582 fast/replaced/replaced-breaking.html [ Failure Pass ]
-crbug.com/1035582 fast/replaced/width100percent-button.html [ Failure Pass ]
-crbug.com/1035582 paint/invalidation/forms/button-checkbox-click-method-repaint.html [ Failure Pass ]
-crbug.com/1035582 paint/invalidation/forms/range-focus-by-mouse-then-keydown.html [ Failure Pass ]
-crbug.com/1035582 paint/invalidation/forms/select-option-background-color.html [ Failure Pass ]
-crbug.com/1035582 svg/custom/foreign-object-skew.svg [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug18359.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug194024.html [ Failure Pass ]
-# Comment back in the Fuchsia one at line 804:
-crbug.com/1035582 tables/mozilla/bugs/bug2479-3.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug33855.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug4382.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug44505.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug51727.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug52505.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug52506.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla/bugs/bug60749.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla_expected_failures/collapsing_borders/bug41262-5.html [ Failure Pass ]
-crbug.com/1035582 tables/mozilla_expected_failures/collapsing_borders/bug41262-6.html [ Failure Pass ]
-crbug.com/1035582 transforms/2d/zoom-menulist.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/button-style-color.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/date/date-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/month/month-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/select/basic-selects.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/submit/submit-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/textarea/textarea-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/text/text-appearance-basic.html [ Failure Pass ]
-crbug.com/1035582 virtual/text-antialias/whitespace/normal-after-nowrap-breaking.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles.html [ Failure Pass ]
-crbug.com/1035582 virtual/web-components-v0-disabled/fast/parser/document-write-option.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/color/color-suggestion-picker-appearance.html [ Failure Pass ]
-crbug.com/1035582 virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125.html [ Failure Pass ]
 
 # These need test modification: the Color picker now pops up a dialog.
 crbug.com/1035582 external/wpt/css/selectors/focus-visible-003-manual.html [ Skip ]
 crbug.com/1035582 external/wpt/css/selectors/focus-visible-004-manual.html [ Skip ]
 
-# These fail only on Windows:
+# These fail only on Windows (and Linux; see a section further below):
 crbug.com/1035582 [ Win ] fast/forms/range/slider-mouse-events.html [ Failure Pass ]
 crbug.com/1035582 [ Win ] fast/forms/range/slider-zoomed.html [ Failure Pass ]
 crbug.com/1035582 [ Win ] fast/forms/select-popup/popup-menu-appearance-coarse.html [ Failure Pass ]
@@ -2358,10 +2300,388 @@
 crbug.com/1035582 [ Win ] external/wpt/css/css-pseudo/spelling-error-002-manual.html [ Failure Pass ]
 crbug.com/1035582 [ Win ] external/wpt/css/css-pseudo/spelling-error-003-manual.html [ Failure Pass ]
 
-# These fail only on Linux, and only (?) in the non_skia_renderer_swiftshader_blink_web_tests suite:
+# When testing locally on Linux, the list of failures seems to be identical to the one for Windows (see above):
+crbug.com/1035582 [ Linux ] fast/forms/range/slider-mouse-events.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/range/slider-zoomed.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-coarse.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-empty.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-fractional-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-long.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-many.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-minimum-font.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-rtl-default.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-rtl.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-single-option.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-styled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-texttransform.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-zoom090.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-zoom110.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select-popup/popup-menu-appearance-zoom.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/hidpi/scrollbar-appearance-increase-device-scale-factor.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/submit-focus-by-mouse-then-keydown.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/audio-service/http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/cascade/fast/forms/select-popup/popup-menu-appearance-zoom090.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/cascade/fast/forms/select-popup/popup-menu-appearance-zoom110.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/layout_ng_flex_box/css3/flexbox/button.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/prefer_compositing_to_lcd_text/compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/prefer_compositing_to_lcd_text/compositing/overflow/theme-affects-visual-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/prefer_compositing_to_lcd_text/compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/prefer_compositing_to_lcd_text/scrollbars/listbox-scrollbar-combinations.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/caps-lock-indicator-disabled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/caps-lock-indicator-enabled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/caps-lock-indicator-enabled-rtl.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/international/hindi-spacing.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/international/rtl-white-space-pre-wrap.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/international/unicode-bidi-plaintext-in-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/selection/mixed-directionality-selection.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/text-antialias/updateNewFont.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-repaint-on-update-value.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-changing-pseudo.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/dom/HTMLProgressElement/progress-element.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/parser/bad-xml-slash.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/parser/entity-comment-in-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/fast/parser/open-comment-in-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-no-summary4.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-open2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-open4.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-open-javascript.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-replace-summary-child.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/web-components-v0-disabled/html/details_summary/details-replace-text.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] compositing/overflow/theme-affects-visual-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css1/box_properties/acid_test.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css2.1/t09-c5526c-display-00-e.html [ Failure Pass ]
 crbug.com/1035582 [ Linux ] css3/flexbox/button.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-161.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-23.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-24.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-25.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-64.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-68.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-69.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/html/css3-modsel-70.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-161.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-23.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-24.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-25.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-64.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-68.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-69.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xhtml/css3-modsel-70.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-161.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-23.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-24.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-25.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-64.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-68.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-69.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] css3/selectors3/xml/css3-modsel-70.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-001.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-002.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-003.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-004.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-005.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-007.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-010.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-color-012.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/caret/caret-position.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/input/caret-at-the-edge-of-input.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/input/reveal-caret-of-multiline-input.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/inserting/4960120-1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/pasteboard/4806874.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/selection/4975120.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] editing/selection/selection-button-text.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] external/wpt/css/css-transforms/transform-input-015.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/block/basic/011.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/block/float/032.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/block/float/overhanging-tall-block.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/block/positioning/inline-block-relposition.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/css/input-search-padding.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/css/line-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/css/non-standard-checkbox-size.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/css/resize-corner-tracking.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/css/rtl-ordering.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/dom/HTMLMeterElement/meter-element.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/dom/HTMLMeterElement/meter-element-repaint-on-update-value.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/dom/HTMLMeterElement/meter-styles-changing-pseudo.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/dom/HTMLProgressElement/progress-element.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/dynamic/008.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/files/file-in-input-display.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/001.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/blankbuttons.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/button/button-cannot-be-nested.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/button/button-inner-block-reuse.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/button/button-with-float.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/button-default-title.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/button-positioned.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/checkbox/checkbox-appearance-basic.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/control-clip.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/control-clip-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/date/date-appearance-pseudo-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/encoding-test.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/fieldset/fieldset-align.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/file/file-input-disabled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/file/file-input-pressed-state.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/file/input-file-re-render.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/floating-textfield-relayout.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/formmove2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/formmove3.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/formmove.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/huge-mac-input-clamped-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/huge-mac-input-clamped-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/indeterminate.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/input-align.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/input-first-letter.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/input-type-text-min-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/minWidthPercent.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/month/month-appearance-pseudo-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/number/number-appearance-rtl.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/number/number-appearance-spinbutton-layer.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/plaintext-mode-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/radio/radio-appearance-basic.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/range/range-update.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/range/slider-thumb-shared-style.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/search/search-cancel-button-style-sharing.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/search/search-display-none-cancel-button.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/search/searchfield-heights.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/search/search-rtl.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/003.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/004.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/HTMLOptionElement_label01.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/HTMLOptionElement_label05.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/HTMLOptionElement_label06.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/HTMLOptionElement_label07.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-appearance-separator.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-clip.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-overlay-scrollbar.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-scrollbar-incremental-load.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-width-change.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/listbox-with-display-none-option.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-appearance-none.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-clip.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-deselect-update.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-narrow-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-no-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-option-wrap.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-restrict-line-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-separator-painting.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-style-color.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/menulist-width-change.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/multiselect-in-listbox-keyboard-focusring.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/optgroup-rendering.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/option-script.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/option-text-clip.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-autofilled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-background-none.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-baseline.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-block-background.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-change-listbox-size.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-change-listbox-to-popup.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-change-popup-to-listbox.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-dirty-parent-pref-widths.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-empty-option-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-item-background-clip.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-listbox-multiple-no-focusring.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-list-box-with-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/selectlist-minsize.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-multiple-rtl.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-overflow-scroll.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-overflow-scroll-inherited.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-size-invalid.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-style.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/select/select-visual-hebrew.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/stuff-on-my-optgroup.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/tabbing-input-iframe.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/targeted-frame-submission.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/placeholder-appearance-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/reset-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-align.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-placeholder-visibility-1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-placeholder-visibility-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-scrollbar.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-scrolled-focus-ring.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-scrolled-type.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-scroll-height.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-setinnerhtml.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/textarea/textarea-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-bkcolor.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-default-bkcolor.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-disabled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-focus.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-preventDefault.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-readonly.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-selection.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-visibility.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-appearance-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-baseline.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-double-click-selection-gap-bug.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-field-text-truncated.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-placeholder-visibility-1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-placeholder-visibility-3.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-readonly-autoscroll.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-readonly-dimmed.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-readonly-empty.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-spaces.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-table.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-tab-shows-caret.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-click-inside.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-click-outside.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-double-click.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-drag-down.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-option-delete.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-scroll-left-on-blur.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-self-emptying-click.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-text-word-wrap.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/input-width.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text-style-color.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/textfield-focus-ring.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/textfield-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/text/text-font-height-mismatch.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/time/time-appearance-pseudo-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-appearance-edge.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-appearance-escape.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-appearance-iframe.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-appearance-wrap.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-device-emulation-change.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/validation-bubble-device-emulation.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/visual-hebrew-text-field.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/forms/week/week-appearance-pseudo-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/hidpi/resize-corner-hidpi.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/inline/positionedLifetime.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/invalid/014.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/lists/dynamic-marker-crash.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/multicol/input-with-overflow-second-column.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/overflow/overflow-x-y.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/overflow/scroll-nested-positioned-layer-in-overflow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/overflow/scrollRevealButton.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/parser/bad-xml-slash.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/parser/entity-comment-in-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/parser/open-comment-in-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/replaced-breaking-mixture.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/three-selects-break.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-checkbox.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-menulist.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-radio.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-searchfield.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-textarea.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/replaced/width100percent-textfield.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/selectors/064.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/spatial-navigation/snav-multiple-select-focusring.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/003.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/append-cells2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/colspanMinWidth.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/colspanMinWidth-vertical.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/remove-td-display-none.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/spanOverlapRepaint.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fast/table/text-field-baseline.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] fragmentation/outline-crossing-columns.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-no-summary4.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-open2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-open4.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-open-javascript.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-replace-summary-child.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] html/details_summary/details-replace-text.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] http/tests/filesystem/input-display.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] http/tests/webfont/popup-menu-load-webfont-after-open.html [ Failure Pass ]
 crbug.com/1035582 [ Linux ] images/12-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] images/182.html [ Failure Pass ]
 crbug.com/1035582 [ Linux ] images/23-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] images/2-dht.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] images/55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/caret-subpixel.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/button-reset-focus-by-mouse-then-keydown.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/radio-focus-by-mouse-then-keydown.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/slider-thumb-drag-release.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/forms/textarea-caret.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/renderer-destruction-by-invalidateSelection-crash.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/scroll/caret-invalidation-in-overflow-scroll.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/scroll/caret-with-composited-scroll.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/selection/selection-in-composited-scrolling-container.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/selection/selection-in-non-composited-scrolling-container.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/invalidation/subtree-root-skipped.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/selection/text-selection-with-composition.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] paint/theme/adjust-progress-bar-size.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] scrollbars/listbox-scrollbar-combinations.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] svg/custom/inline-svg-in-xhtml.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] svg/hixie/mixed/003.xml [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/45621.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug1188.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug12384.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug1318.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug138725.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug24200.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug2479-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug26178.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug28928.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug29326.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug30559.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug30692.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug39209.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug4429.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug4527.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug46368-1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug46368-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug51037.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug55545.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug59354.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug68912.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug7342.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug92647-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug96334.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/bugs/bug99948.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/collapsing_borders/bug41262-4.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/core/margins.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/dom/tableDom.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla_expected_failures/bugs/bug1725.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla_expected_failures/bugs/bug58402-2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla_expected_failures/bugs/bug92647-1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla_expected_failures/core/captions1.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla_expected_failures/core/captions2.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] tables/mozilla/other/move_row.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] transforms/3d/general/perspective-non-layer.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] transforms/transformed-focused-text-input.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/cascade/fast/forms/001.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/cascade/fast/forms/fieldset/fieldset-align.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/cascade/fast/forms/select/select-autofilled.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/dark-mode-native-theme-off/text-input-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/dark-mode-native-theme-on/text-input-elements.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/exotic-color-space/images/12-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/exotic-color-space/images/182.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/exotic-color-space/images/23-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/exotic-color-space/images/2-dht.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/exotic-color-space/images/55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/gpu-rasterization/images/12-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/gpu-rasterization/images/182.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/gpu-rasterization/images/23-55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/gpu-rasterization/images/2-dht.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/gpu-rasterization/images/55.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/layout_ng_block_frag/fast/multicol/input-with-overflow-second-column.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/layout_ng_block_frag/fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] virtual/layout_ng_block_frag/fragmentation/outline-crossing-columns.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] external/wpt/css/css-pseudo/spelling-error-002-manual.html [ Failure Pass ]
+crbug.com/1035582 [ Linux ] external/wpt/css/css-pseudo/spelling-error-003-manual.html [ Failure Pass ]
+
+# Problems rebaselining:
+crbug.com/1035582 virtual/cascade/fast/forms/date/date-appearance-basic.html [ Skip ]
+crbug.com/1035582 virtual/cascade/fast/forms/month/month-appearance-basic.html [ Skip ]
+crbug.com/1035582 wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.html [ Skip ]
+
+# I don't know why this one is failing:
+crbug.com/1035582 [ Win ] wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any-expected.txt [ Skip ]
 
 # End of rebaselines for crbug.com/1035582.
 # ======
@@ -3352,6 +3672,7 @@
 crbug.com/1035708 external/wpt/css/css-pseudo/grammar-error-001.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac10.11 ] virtual/cascade/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html [ Failure ]
 crbug.com/626703 [ Mac10.13 ] virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/infrastructure/reftest/reftest_match_and_mismatch-6.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/infrastructure/reftest/reftest_match_and_mismatch-6.html [ Failure ]
@@ -5078,16 +5399,9 @@
 crbug.com/678493 http/tests/permissions/chromium/test-request-window.html [ Timeout Pass ]
 crbug.com/678499 http/tests/security/contentSecurityPolicy/require-sri-for/require-sri-for-script-preload-allowed.php [ Failure Pass ]
 
+crbug.com/747751 [ Win ] http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Failure Pass ]
 crbug.com/747751 http/tests/devtools/application-panel/storage-view-reports-quota.js [ Pass Timeout ]
 
-crbug.com/1038678 http/tests/devtools/application-panel/resources-panel-iframe-idb.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/application-panel/resources-panel-on-navigation.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/application-panel/resources-panel-selection-on-reload.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/application-panel/resources-panel-websql.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/service-workers/service-workers-redundant.js [ Skip ]
-crbug.com/1038678 http/tests/devtools/service-workers/service-workers-view.js [ Skip ]
-
 crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ]
 crbug.com/689781 [ Win ] http/tests/media/media-source/mediasource-duration.html [ Failure Pass ]
 crbug.com/689781 [ Mac ] http/tests/media/media-source/mediasource-duration.html [ Failure Pass ]
@@ -6795,7 +7109,7 @@
 # Sheriff 2019-12-13
 crbug.com/1032451 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window.html [ Failure Timeout Pass ]
 crbug.com/1033852 [ Win7 ] virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.sharedworker.html [ Failure ]
-crbug.com/1033387 [ Mac ] http/tests/portals/crbug-1031677.html [ Pass Timeout ]
+crbug.com/1033387 [ Mac ] http/tests/portals/crbug-1031677.html [ Pass Timeout Crash ]
 
 # Sheriff 2019-12-16
 crbug.com/1034374 http/tests/devtools/tracing/timeline-worker-events.js [ Pass Failure ]
@@ -6835,6 +7149,9 @@
 # Sheriff 2019-12-30
 crbug.com/1038354 fast/scroll-snap/snaps-after-scrollbar-scrolling.html [ Pass Failure ]
 
+# These tests will pass once the --enable-features=WebBundlesFromNetwork flag is enabled by default.
+crbug.com/1018640 external/wpt/web-bundle/* [ Skip ]
+
 # Sheriff 2020-01-02
 crbug.com/1038656 [ Mac ] http/tests/devtools/coverage/coverage-view-unused.js [ Pass Failure ]
 crbug.com/1038656 [ Win ] http/tests/devtools/coverage/coverage-view-unused.js [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 914e6c1..6b4c7b3 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -339,6 +339,12 @@
     "args": ["--enable-features=SignedExchangeSubresourcePrefetch"]
   },
   {
+    "prefix": "wbn-from-network",
+    "bases": ["external/wpt/web-bundle"],
+    "args": ["--enable-features=WebBundlesFromNetwork"]
+  },
+
+  {
     "prefix": "omt-service-worker-startup",
     "bases": ["external/wpt/service-workers",
               "external/wpt/shape-detection",
diff --git a/third_party/blink/web_tests/animations/composition/box-shadow-composition.html b/third_party/blink/web_tests/animations/composition/box-shadow-composition.html
index 98955aa1..8d111e1 100644
--- a/third_party/blink/web_tests/animations/composition/box-shadow-composition.html
+++ b/third_party/blink/web_tests/animations/composition/box-shadow-composition.html
@@ -19,11 +19,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px 80px',
 }, [
-  {at: -0.3, is: 'rgb(80, 90, 100) 8px 16px 24px 32px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px 44px'},
-  {at: 0.5, is: 'rgb(160, 170, 180) 16px 32px 48px 64px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px 84px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26px 52px 78px 104px'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(70, 70, 70) 7px 14px 21px 28px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(100, 100, 100) 10px 20px 30px 40px'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(150, 150, 150) 15px 30px 45px 60px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(200, 200, 200) 20px 40px 60px 80px'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(250, 250, 250) 25px 50px 75px 100px'},
 ]);
 
 assertComposition({
@@ -32,11 +32,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px inset',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px 80px inset',
 }, [
-  {at: -0.3, is: 'rgb(70, 70, 70) 7px 14px 21px 28px inset'},
-  {at: 0, is: 'rgb(100, 100, 100) 10px 20px 30px 40px inset'},
-  {at: 0.5, is: 'rgb(150, 150, 150) 15px 30px 45px 60px inset'},
-  {at: 1, is: 'rgb(200, 200, 200) 20px 40px 60px 80px inset'},
-  {at: 1.5, is: 'rgb(250, 250, 250) 25px 50px 75px 100px inset'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(70, 70, 70) 7px 14px 21px 28px inset'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(100, 100, 100) 10px 20px 30px 40px inset'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(150, 150, 150) 15px 30px 45px 60px inset'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(200, 200, 200) 20px 40px 60px 80px inset'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(250, 250, 250) 25px 50px 75px 100px inset'},
 ]);
 
 assertComposition({
@@ -45,11 +45,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px 80px',
 }, [
-  {at: -0.3, is: 'rgb(80, 90, 100) 8px 16px 24px 32px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px 44px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 0.5, is: 'rgb(160, 170, 180) 16px 32px 48px 64px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px 84px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26px 52px 78px 104px, rgb(20, 40, 60) 2px 4px 6px 8px'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(70, 70, 70) 7px 14px 21px 28px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(100, 100, 100) 10px 20px 30px 40px'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(150, 150, 150) 15px 30px 45px 60px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(200, 200, 200) 20px 40px 60px 80px'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(250, 250, 250) 25px 50px 75px 100px'},
 ]);
 
 assertComposition({
@@ -58,11 +58,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px, rgb(100, 100, 100) 10px 20px 30px 40px inset',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px 80px, rgb(200, 200, 200) 20px 40px 60px 80px inset',
 }, [
-  {at: -0.3, is: 'rgb(80, 90, 100) 8px 16px 24px 32px, rgb(70, 70, 70) 7px 14px 21px 28px inset'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px 44px, rgb(100, 100, 100) 10px 20px 30px 40px inset'},
-  {at: 0.5, is: 'rgb(160, 170, 180) 16px 32px 48px 64px, rgb(150, 150, 150) 15px 30px 45px 60px inset'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px 84px, rgb(200, 200, 200) 20px 40px 60px 80px inset'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26px 52px 78px 104px, rgb(250, 250, 250) 25px 50px 75px 100px inset'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(70, 70, 70) 7px 14px 21px 28px, rgb(70, 70, 70) 7px 14px 21px 28px inset'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(100, 100, 100) 10px 20px 30px 40px, rgb(100, 100, 100) 10px 20px 30px 40px inset'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(150, 150, 150) 15px 30px 45px 60px, rgb(150, 150, 150) 15px 30px 45px 60px inset'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(200, 200, 200) 20px 40px 60px 80px, rgb(200, 200, 200) 20px 40px 60px 80px inset'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(250, 250, 250) 25px 50px 75px 100px, rgb(250, 250, 250) 25px 50px 75px 100px inset'},
 ]);
 
 assertComposition({
@@ -71,11 +71,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px',
   replaceTo: 'rgb(200, 200, 200) 20px 40px 60px 80px',
 }, [
-  {at: -0.3, is: 'rgb(83, 96, 109) 8.3px 16.6px 24.9px 33.2px, rgb(26, 52, 78) 2.6px 5.2px 7.8px 10.4px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px 44px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px 62px, rgba(20, 40, 60, 0.5) 1px 2px 3px 4px'},
+  {at: -0.3, is: 'rgb(0, 0, 0) -4.7px -9.4px 0px -18.8px, rgb(26, 52, 78) 2.6px 5.2px 7.8px 10.4px, rgb(130, 130, 130) 13px 26px 39px 52px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(100, 100, 100) 10px 20px 30px 40px'},
+  {at: 0.5, is: 'rgb(105, 110, 115) 10.5px 21px 31.5px 42px, rgba(20, 40, 60, 0.5) 1px 2px 3px 4px, rgba(100, 100, 100, 0.5) 5px 10px 15px 20px'},
   {at: 1, is: 'rgb(200, 200, 200) 20px 40px 60px 80px'},
-  {at: 1.5, is: 'rgba(255, 255, 255, 0.5) 24.5px 49px 73.5px 98px, rgba(0, 0, 0, 0) -1px -2px 0px -4px'},
+  {at: 1.5, is: 'rgb(255, 255, 255) 29.5px 59px 88.5px 118px, rgba(0, 0, 0, 0) -1px -2px 0px -4px, rgba(0, 0, 0, 0) -5px -10px 0px -20px'},
 ]);
 
 assertComposition({
@@ -84,11 +84,11 @@
   replaceFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px 80px',
 }, [
-  {at: -0.3, is: 'rgba(96, 91, 87, 0.7) 6.7px 13.4px 20.1px 26.8px, rgba(0, 0, 0, 0) -0.6px -1.2px 0px -2.4px'},
+  {at: -0.3, is: 'rgb(127, 124, 121) 12.7px 25.4px 38.1px 50.8px, rgba(0, 0, 0, 0) -0.6px -1.2px 0px -2.4px, rgba(0, 0, 0, 0) -6px -12px 0px -24px'},
   {at: 0, is: 'rgb(100, 100, 100) 10px 20px 30px 40px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px 62px, rgba(20, 40, 60, 0.5) 1px 2px 3px 4px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px 84px, rgb(20, 40, 60) 2px 4px 6px 8px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26.5px 53px 79.5px 106px, rgb(30, 60, 90) 3px 6px 9px 12px'},
+  {at: 0.5, is: 'rgb(55, 60, 65) 5.5px 11px 16.5px 22px, rgba(20, 40, 60, 0.5) 1px 2px 3px 4px, rgba(200, 200, 200, 0.5) 10px 20px 30px 40px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(200, 200, 200) 20px 40px 60px 80px'},
+  {at: 1.5, is: 'rgb(0, 0, 0) -3.5px -7px 0px -14px, rgb(30, 60, 90) 3px 6px 9px 12px, rgb(255, 255, 255) 30px 60px 90px 120px'},
 ]);
 
 assertComposition({
@@ -97,11 +97,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px 40px, rgb(200, 200, 200) 20px 40px 60px 80px',
   replaceTo: 'rgb(200, 200, 200) 20px 40px 60px 80px',
 }, [
-  {at: -0.3, is: 'rgb(83, 96, 109) 8.3px 16.6px 24.9px 33.2px, rgb(255, 255, 255) 28.6px 57.2px 85.8px 114.4px, rgb(52, 104, 156) 5.2px 10.4px 15.6px 20.8px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px 44px, rgb(220, 240, 255) 22px 44px 66px 88px, rgb(40, 80, 120) 4px 8px 12px 16px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px 62px, rgb(110, 120, 130) 11px 22px 33px 44px, rgba(40, 80, 120, 0.5) 2px 4px 6px 8px'},
+  {at: -0.3, is: 'rgb(0, 0, 0) -4.7px -9.4px 0px -18.8px, rgb(26, 52, 78) 2.6px 5.2px 7.8px 10.4px, rgb(52, 104, 156) 5.2px 10.4px 15.6px 20.8px, rgb(130, 130, 130) 13px 26px 39px 52px, rgb(255, 255, 255) 26px 52px 78px 104px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px 4px, rgb(20, 40, 60) 2px 4px 6px 8px, rgb(40, 80, 120) 4px 8px 12px 16px, rgb(100, 100, 100) 10px 20px 30px 40px, rgb(200, 200, 200) 20px 40px 60px 80px'},
+  {at: 0.5, is: 'rgb(105, 110, 115) 10.5px 21px 31.5px 42px, rgba(20, 40, 60, 0.5) 1px 2px 3px 4px, rgba(40, 80, 120, 0.5) 2px 4px 6px 8px, rgba(100, 100, 100, 0.5) 5px 10px 15px 20px, rgba(200, 200, 200, 0.5) 10px 20px 30px 40px'},
   {at: 1, is: 'rgb(200, 200, 200) 20px 40px 60px 80px'},
-  {at: 1.5, is: 'rgba(255, 255, 255, 0.5) 24.5px 49px 73.5px 98px, rgba(0, 0, 0, 0) -11px -22px 0px -44px, rgba(0, 0, 0, 0) -2px -4px 0px -8px'},
+  {at: 1.5, is: 'rgb(255, 255, 255) 29.5px 59px 88.5px 118px, rgba(0, 0, 0, 0) -1px -2px 0px -4px, rgba(0, 0, 0, 0) -2px -4px 0px -8px, rgba(0, 0, 0, 0) -5px -10px 0px -20px, rgba(0, 0, 0, 0) -10px -20px 0px -40px'},
 ]);
 </script>
 </body>
diff --git a/third_party/blink/web_tests/animations/composition/text-shadow-composition.html b/third_party/blink/web_tests/animations/composition/text-shadow-composition.html
index 27ecda4a..6ec0647 100644
--- a/third_party/blink/web_tests/animations/composition/text-shadow-composition.html
+++ b/third_party/blink/web_tests/animations/composition/text-shadow-composition.html
@@ -19,11 +19,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px',
 }, [
-  {at: -0.3, is: 'rgb(80, 90, 100) 8px 16px 24px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px'},
-  {at: 0.5, is: 'rgb(160, 170, 180) 16px 32px 48px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26px 52px 78px'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(70, 70, 70) 7px 14px 21px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(100, 100, 100) 10px 20px 30px'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(150, 150, 150) 15px 30px 45px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(200, 200, 200) 20px 40px 60px'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(250, 250, 250) 25px 50px 75px'},
 ]);
 
 assertComposition({
@@ -32,11 +32,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px',
 }, [
-  {at: -0.3, is: 'rgb(80, 90, 100) 8px 16px 24px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 0.5, is: 'rgb(160, 170, 180) 16px 32px 48px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26px 52px 78px, rgb(20, 40, 60) 2px 4px 6px'},
+  {at: -0.3, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(70, 70, 70) 7px 14px 21px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(100, 100, 100) 10px 20px 30px'},
+  {at: 0.5, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(150, 150, 150) 15px 30px 45px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(200, 200, 200) 20px 40px 60px'},
+  {at: 1.5, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(250, 250, 250) 25px 50px 75px'},
 ]);
 
 assertComposition({
@@ -45,11 +45,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px',
   replaceTo: 'rgb(200, 200, 200) 20px 40px 60px',
 }, [
-  {at: -0.3, is: 'rgb(83, 96, 109) 8.3px 16.6px 24.9px, rgb(26, 52, 78) 2.6px 5.2px 7.8px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px, rgba(20, 40, 60, 0.5) 1px 2px 3px'},
+  {at: -0.3, is: 'rgb(0, 0, 0) -4.7px -9.4px 0px, rgb(26, 52, 78) 2.6px 5.2px 7.8px, rgb(130, 130, 130) 13px 26px 39px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(100, 100, 100) 10px 20px 30px'},
+  {at: 0.5, is: 'rgb(105, 110, 115) 10.5px 21px 31.5px, rgba(20, 40, 60, 0.5) 1px 2px 3px, rgba(100, 100, 100, 0.5) 5px 10px 15px'},
   {at: 1, is: 'rgb(200, 200, 200) 20px 40px 60px'},
-  {at: 1.5, is: 'rgba(255, 255, 255, 0.5) 24.5px 49px 73.5px, rgba(0, 0, 0, 0) -1px -2px 0px'},
+  {at: 1.5, is: 'rgb(255, 255, 255) 29.5px 59px 88.5px, rgba(0, 0, 0, 0) -1px -2px 0px, rgba(0, 0, 0, 0) -5px -10px 0px'},
 ]);
 
 assertComposition({
@@ -58,11 +58,11 @@
   replaceFrom: 'rgb(100, 100, 100) 10px 20px 30px',
   addTo: 'rgb(200, 200, 200) 20px 40px 60px',
 }, [
-  {at: -0.3, is: 'rgba(96, 91, 87, 0.7) 6.7px 13.4px 20.1px, rgba(0, 0, 0, 0) -0.6px -1.2px 0px'},
+  {at: -0.3, is: 'rgb(127, 124, 121) 12.7px 25.4px 38.1px, rgba(0, 0, 0, 0) -0.6px -1.2px 0px, rgba(0, 0, 0, 0) -6px -12px 0px'},
   {at: 0, is: 'rgb(100, 100, 100) 10px 20px 30px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px, rgba(20, 40, 60, 0.5) 1px 2px 3px'},
-  {at: 1, is: 'rgb(210, 220, 230) 21px 42px 63px, rgb(20, 40, 60) 2px 4px 6px'},
-  {at: 1.5, is: 'rgb(255, 255, 255) 26.5px 53px 79.5px, rgb(30, 60, 90) 3px 6px 9px'},
+  {at: 0.5, is: 'rgb(55, 60, 65) 5.5px 11px 16.5px, rgba(20, 40, 60, 0.5) 1px 2px 3px, rgba(200, 200, 200, 0.5) 10px 20px 30px'},
+  {at: 1, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(200, 200, 200) 20px 40px 60px'},
+  {at: 1.5, is: 'rgb(0, 0, 0) -3.5px -7px 0px, rgb(30, 60, 90) 3px 6px 9px, rgb(255, 255, 255) 30px 60px 90px'},
 ]);
 
 assertComposition({
@@ -71,11 +71,11 @@
   addFrom: 'rgb(100, 100, 100) 10px 20px 30px, rgb(200, 200, 200) 20px 40px 60px',
   replaceTo: 'rgb(200, 200, 200) 20px 40px 60px',
 }, [
-  {at: -0.3, is: 'rgb(83, 96, 109) 8.3px 16.6px 24.9px, rgb(255, 255, 255) 28.6px 57.2px 85.8px, rgb(52, 104, 156) 5.2px 10.4px 15.6px'},
-  {at: 0, is: 'rgb(110, 120, 130) 11px 22px 33px, rgb(220, 240, 255) 22px 44px 66px, rgb(40, 80, 120) 4px 8px 12px'},
-  {at: 0.5, is: 'rgb(155, 160, 165) 15.5px 31px 46.5px, rgb(110, 120, 130) 11px 22px 33px, rgba(40, 80, 120, 0.5) 2px 4px 6px'},
+  {at: -0.3, is: 'rgb(0, 0, 0) -4.7px -9.4px 0px, rgb(26, 52, 78) 2.6px 5.2px 7.8px, rgb(52, 104, 156) 5.2px 10.4px 15.6px, rgb(130, 130, 130) 13px 26px 39px, rgb(255, 255, 255) 26px 52px 78px'},
+  {at: 0, is: 'rgb(10, 20, 30) 1px 2px 3px, rgb(20, 40, 60) 2px 4px 6px, rgb(40, 80, 120) 4px 8px 12px, rgb(100, 100, 100) 10px 20px 30px, rgb(200, 200, 200) 20px 40px 60px'},
+  {at: 0.5, is: 'rgb(105, 110, 115) 10.5px 21px 31.5px, rgba(20, 40, 60, 0.5) 1px 2px 3px, rgba(40, 80, 120, 0.5) 2px 4px 6px, rgba(100, 100, 100, 0.5) 5px 10px 15px, rgba(200, 200, 200, 0.5) 10px 20px 30px'},
   {at: 1, is: 'rgb(200, 200, 200) 20px 40px 60px'},
-  {at: 1.5, is: 'rgba(255, 255, 255, 0.5) 24.5px 49px 73.5px, rgba(0, 0, 0, 0) -11px -22px 0px, rgba(0, 0, 0, 0) -2px -4px 0px'},
+  {at: 1.5, is: 'rgb(255, 255, 255) 29.5px 59px 88.5px, rgba(0, 0, 0, 0) -1px -2px 0px, rgba(0, 0, 0, 0) -2px -4px 0px, rgba(0, 0, 0, 0) -5px -10px 0px, rgba(0, 0, 0, 0) -10px -20px 0px'},
 ]);
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index cad868a..afb24b2 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -58223,6 +58223,18 @@
      {}
     ]
    ],
+   "css/css-multicol/change-intrinsic-width.html": [
+    [
+     "css/css-multicol/change-intrinsic-width.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-multicol/column-count-used-001.html": [
     [
      "css/css-multicol/column-count-used-001.html",
@@ -58343,6 +58355,18 @@
      {}
     ]
    ],
+   "css/css-multicol/intrinsic-width-change-column-count.html": [
+    [
+     "css/css-multicol/intrinsic-width-change-column-count.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-multicol/large-actual-column-count.html": [
     [
      "css/css-multicol/large-actual-column-count.html",
@@ -128520,6 +128544,15 @@
    "WebCryptoAPI/generateKey/successes_AES-KW.https.worker-expected.txt": [
     []
    ],
+   "WebCryptoAPI/historical.any-expected.txt": [
+    []
+   ],
+   "WebCryptoAPI/historical.any.sharedworker-expected.txt": [
+    []
+   ],
+   "WebCryptoAPI/historical.any.worker-expected.txt": [
+    []
+   ],
    "WebCryptoAPI/idlharness.https.worker-expected.txt": [
     []
    ],
@@ -165141,6 +165174,9 @@
    "html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt": [
     []
    ],
+   "html/semantics/forms/constraints/form-validation-willValidate-expected.txt": [
+    []
+   ],
    "html/semantics/forms/constraints/support/validator.js": [
     []
    ],
@@ -166833,9 +166869,6 @@
    "imagebitmap-renderingcontext/context-creation-offscreen-expected.txt": [
     []
    ],
-   "imagebitmap-renderingcontext/context-preserves-canvas-expected.txt": [
-    []
-   ],
    "images/META.yml": [
     []
    ],
@@ -174648,9 +174681,6 @@
    "service-workers/cache-storage/worker/cache-storage.https-expected.txt": [
     []
    ],
-   "service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt": [
-    []
-   ],
    "service-workers/service-worker/ServiceWorkerGlobalScope/isSecureContext.serviceworker.js": [
     []
    ],
@@ -182040,6 +182070,27 @@
    "web-animations/timing-model/animations/update-playback-rate-zero-ref.html": [
     []
    ],
+   "web-bundle/META.yml": [
+    []
+   ],
+   "web-bundle/README.md": [
+    []
+   ],
+   "web-bundle/resources/generate-test-wbns.sh": [
+    []
+   ],
+   "web-bundle/resources/location/location.html": [
+    []
+   ],
+   "web-bundle/resources/location/location.js": [
+    []
+   ],
+   "web-bundle/resources/wbn/__dir__.headers": [
+    []
+   ],
+   "web-bundle/resources/wbn/location.wbn": [
+    []
+   ],
    "web-locks/META.yml": [
     []
    ],
@@ -200891,6 +200942,41 @@
      {}
     ]
    ],
+   "WebCryptoAPI/historical.any.js": [
+    [
+     "WebCryptoAPI/historical.any.html",
+     {
+      "script_metadata": [
+       [
+        "global",
+        "window,dedicatedworker,sharedworker"
+       ]
+      ]
+     }
+    ],
+    [
+     "WebCryptoAPI/historical.any.sharedworker.html",
+     {
+      "script_metadata": [
+       [
+        "global",
+        "window,dedicatedworker,sharedworker"
+       ]
+      ]
+     }
+    ],
+    [
+     "WebCryptoAPI/historical.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "global",
+        "window,dedicatedworker,sharedworker"
+       ]
+      ]
+     }
+    ]
+   ],
    "WebCryptoAPI/idlharness.https.any.js": [
     [
      "WebCryptoAPI/idlharness.https.any.html",
@@ -200959,12 +201045,6 @@
      {}
     ]
    ],
-   "WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html": [
-    [
-     "WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html",
-     {}
-    ]
-   ],
    "WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html": [
     [
      "WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html",
@@ -212758,6 +212838,12 @@
      {}
     ]
    ],
+   "css/css-content/computed-value.html": [
+    [
+     "css/css-content/computed-value.html",
+     {}
+    ]
+   ],
    "css/css-content/inheritance.html": [
     [
      "css/css-content/inheritance.html",
@@ -227712,6 +227798,12 @@
      {}
     ]
    ],
+   "css/cssom-view/getClientRects-inline-inline-child.html": [
+    [
+     "css/cssom-view/getClientRects-inline-inline-child.html",
+     {}
+    ]
+   ],
    "css/cssom-view/historical.html": [
     [
      "css/cssom-view/historical.html",
@@ -231907,6 +231999,12 @@
      {}
     ]
    ],
+   "dom/nodes/Node-appendChild-cereactions-vs-script.window.js": [
+    [
+     "dom/nodes/Node-appendChild-cereactions-vs-script.window.html",
+     {}
+    ]
+   ],
    "dom/nodes/Node-appendChild.html": [
     [
      "dom/nodes/Node-appendChild.html",
@@ -318360,6 +318458,12 @@
      }
     ]
    ],
+   "web-bundle/wbn-location.tentative.html": [
+    [
+     "web-bundle/wbn-location.tentative.html",
+     {}
+    ]
+   ],
    "web-locks/acquire.tentative.https.any.js": [
     [
      "web-locks/acquire.tentative.https.any.html",
@@ -347047,6 +347151,22 @@
    "dd970ebfa60cdc96c64da1c9d7f326bc1bcaad01",
    "testharness"
   ],
+  "WebCryptoAPI/historical.any-expected.txt": [
+   "dd5ffd7a6406cd18e43119b493c546ce1df45e81",
+   "support"
+  ],
+  "WebCryptoAPI/historical.any.js": [
+   "67ca9d9767df9d37c841bece0127f04cc5218f56",
+   "testharness"
+  ],
+  "WebCryptoAPI/historical.any.sharedworker-expected.txt": [
+   "dd5ffd7a6406cd18e43119b493c546ce1df45e81",
+   "support"
+  ],
+  "WebCryptoAPI/historical.any.worker-expected.txt": [
+   "dd5ffd7a6406cd18e43119b493c546ce1df45e81",
+   "support"
+  ],
   "WebCryptoAPI/idlharness.https.any.js": [
    "b0ccebd9f48999284ec36dbfb11a35314efa3135",
    "testharness"
@@ -347099,10 +347219,6 @@
    "e82c4d78f6baf44d5abeeafeb5a439508a65eaaf",
    "testharness"
   ],
-  "WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html": [
-   "79bcec7a4dae8bce505e0dad690a47e44b087c7b",
-   "testharness"
-  ],
   "WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html": [
    "67f7ff0b2b8038b14faa32a16a1a06f12ab9577f",
    "testharness"
@@ -377783,6 +377899,10 @@
    "e0cf16bd42aac09242cf10830b0885407348cf92",
    "reftest"
   ],
+  "css/css-content/computed-value.html": [
+   "505d4b4d006e7788345e765fe1d278cd4b176214",
+   "testharness"
+  ],
   "css/css-content/element-replacement-alt-ref.html": [
    "ef8a6f3953c239733026c92541789ca5b942178b",
    "support"
@@ -397447,6 +397567,10 @@
    "434dc52ea3d731bd1393270372294cd007382e59",
    "testharness"
   ],
+  "css/css-multicol/change-intrinsic-width.html": [
+   "3df3e1ebc8f9b5780dc858a878bca13dbedcdb35",
+   "reftest"
+  ],
   "css/css-multicol/column-count-used-001.html": [
    "2949a1996ebae0c48329906ea7ef34c83080e90f",
    "reftest"
@@ -397511,6 +397635,10 @@
    "ce8011b17f82407599ea28a2eaf543ec9d45a98b",
    "reftest"
   ],
+  "css/css-multicol/intrinsic-width-change-column-count.html": [
+   "30e7671e41c3879ceef30627b3d5b65dc8c0ff86",
+   "reftest"
+  ],
   "css/css-multicol/large-actual-column-count.html": [
    "615e3f2f0598973d66518b7abbabe2fbf2f76bda",
    "reftest"
@@ -432491,6 +432619,10 @@
    "f1f6fc5abc679d087d221573456eb9219d1a405c",
    "testharness"
   ],
+  "css/cssom-view/getClientRects-inline-inline-child.html": [
+   "9a03ccdbccc80d8a0ce6f701aeaa802b1b4715e4",
+   "testharness"
+  ],
   "css/cssom-view/getClientRects-inline.html": [
    "415e34a6f0430e08441ee32b3f7c0ca8cd11a692",
    "reftest"
@@ -443656,11 +443788,11 @@
    "testharness"
   ],
   "dom/historical-expected.txt": [
-   "2c0959b792338984140c1b30f5a9e2baab7f95ec",
+   "4c0f1de272a71260bffdf9500383d81fafba50e2",
    "support"
   ],
   "dom/historical.html": [
-   "921fa07b3f6de0f9a579b75b14d6509039765205",
+   "8a71e364e5ef30a0f9d9621d3eb018a34d42ae4c",
    "testharness"
   ],
   "dom/idlharness.any.js": [
@@ -443820,15 +443952,15 @@
    "testharness"
   ],
   "dom/nodes/Document-constructor-svg.svg": [
-   "28aaf16bdcd182f0a754e197d9b250475e59c762",
+   "77e3d8996e6bbc71bd1521903115b34302e23d36",
    "testharness"
   ],
   "dom/nodes/Document-constructor-xml.xml": [
-   "9aada512c895b9ad91516892007ba1d4ab8d9c1c",
+   "c9fc77580648653750a488994abc314a6b409967",
    "testharness"
   ],
   "dom/nodes/Document-constructor.html": [
-   "ceb41926f85869c996e2cb248e4a1853198b8d3c",
+   "e17de28471d75ea83b9b95ae144a3e3f2c3f1cd4",
    "testharness"
   ],
   "dom/nodes/Document-contentType/contentType/contenttype_bmp.html": [
@@ -444467,6 +444599,10 @@
    "6a27ef77ecacf55a7eaaae18cdd007e017e42cd9",
    "testharness"
   ],
+  "dom/nodes/Node-appendChild-cereactions-vs-script.window.js": [
+   "bc0b8ad6dca55d83f1cfb9788e6ff33df96ab22a",
+   "testharness"
+  ],
   "dom/nodes/Node-appendChild.html": [
    "684607961a7eeaefb17b3a49dbf9ed36a3d7aee6",
    "testharness"
@@ -444480,7 +444616,7 @@
    "testharness"
   ],
   "dom/nodes/Node-cloneNode.html": [
-   "08d620b3b80c483835f5e339c19b885ad036ea27",
+   "d977b2a7ae3ec2ee1ad9eec3c64abc86cc2e2500",
    "testharness"
   ],
   "dom/nodes/Node-compareDocumentPosition.html": [
@@ -456436,7 +456572,7 @@
    "testharness"
   ],
   "html/browsers/windows/browsing-context.html": [
-   "5e99bb522f194e67b78bda958359f8ace011a59c",
+   "430598fb21236c877ff693d63a8c1135e010dae0",
    "testharness"
   ],
   "html/browsers/windows/document-access/document_access_parent_access.tentative.html": [
@@ -456652,7 +456788,7 @@
    "support"
   ],
   "html/cross-origin-embedder-policy/none.https.html": [
-   "f13a7523011674b0bab6b265d481b58649dc5531",
+   "7f296e60441458a5f38dfd351d717845677ce30b",
    "testharness"
   ],
   "html/cross-origin-embedder-policy/none.https.html.headers": [
@@ -458164,7 +458300,7 @@
    "testharness"
   ],
   "html/dom/usvstring-reflection.https.html": [
-   "162d58c50c449da07912fbce7ffa9ad9b7674d0a",
+   "d3c90e593400c69c61d433898cd68cc55d633573",
    "testharness"
   ],
   "html/editing/activation/OWNERS": [
@@ -467696,23 +467832,27 @@
    "testharness"
   ],
   "html/semantics/forms/constraints/form-validation-validity-valid-expected.txt": [
-   "e1bb6e4b43073cbd175e81e16bdeb7455c7c29fb",
+   "b0da38305f70073516805dba54b8fb5f0fda8413",
    "support"
   ],
   "html/semantics/forms/constraints/form-validation-validity-valid.html": [
-   "cec5dcbf0d5cfb340e100a82e723e1d620d16399",
+   "03655ffd2f5ba24b30e6864c8393ecbf36230aef",
    "testharness"
   ],
   "html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt": [
-   "611137c81134a0411e73438d2c158ba7f1eb5346",
+   "b4497dd9a754b12ba2d3a1e76ca03f00b828572c",
    "support"
   ],
   "html/semantics/forms/constraints/form-validation-validity-valueMissing.html": [
-   "3c9e4c4cb096bbe93b540c3f704d0d116a055aba",
+   "2e1c666436a19bc759026ebf55df4a17073ecb5d",
    "testharness"
   ],
+  "html/semantics/forms/constraints/form-validation-willValidate-expected.txt": [
+   "67281aaed55cef66289a65fea8fba31ba2f8b12f",
+   "support"
+  ],
   "html/semantics/forms/constraints/form-validation-willValidate.html": [
-   "6c66559a09a0168070f2520d672de79f3a1261da",
+   "ccd1cf09b907bf91f0454f8bb84d04cdf83a18bd",
    "testharness"
   ],
   "html/semantics/forms/constraints/infinite_backtracking.html": [
@@ -467724,7 +467864,7 @@
    "testharness"
   ],
   "html/semantics/forms/constraints/support/validator.js": [
-   "48c3a5b40e6bbe06b18dde7f473188a827b7de6a",
+   "33508fb3289be3736f6f467957dc6614bec2bc9b",
    "support"
   ],
   "html/semantics/forms/constraints/tooShort-input-email-add-manual.html": [
@@ -474411,12 +474551,8 @@
    "3daa3977898cdd21fa5192f6973f0f5a26294cd9",
    "testharness"
   ],
-  "imagebitmap-renderingcontext/context-preserves-canvas-expected.txt": [
-   "8a5d00137f2c38b868e868748d9b66f844d24f5a",
-   "support"
-  ],
   "imagebitmap-renderingcontext/context-preserves-canvas.html": [
-   "9c3a1fb39f2a75db8cd89c1b2225ce469a1caeec",
+   "b0753a7348d1fe8d45b7cd9311ae0670535f06a3",
    "testharness"
   ],
   "imagebitmap-renderingcontext/toBlob-origin-clean-offscreen.sub.html": [
@@ -477176,7 +477312,7 @@
    "testharness"
   ],
   "lint.whitelist": [
-   "b5a8f80687044b596e449e357f7e731895b3a94d",
+   "62644762ce2bce2cbf0c3c8527cac8384ce00256",
    "support"
   ],
   "loading/lazyload/META.yml": [
@@ -482956,7 +483092,7 @@
    "testharness"
   ],
   "navigation-timing/idlharness.window.js": [
-   "8cc3546b3c27a9d93ee5621584d83d56a308513c",
+   "2ec9c754987a66a144c79a0fcc127dd468b62695",
    "testharness"
   ],
   "navigation-timing/nav2_data_uri.html": [
@@ -506636,7 +506772,7 @@
    "support"
   ],
   "resources/chromium/nfc-mock.js": [
-   "4bafc9b0ad8f7f8ad4185914fffef16949695ab3",
+   "2c1724b7592eb1d6e66177544998abbec70fbfe6",
    "support"
   ],
   "resources/chromium/sensor.mojom.js": [
@@ -507340,7 +507476,7 @@
    "testharness"
   ],
   "server-timing/idlharness.https.any.js": [
-   "ded320f0f61f4de1132d5cfb76a7e74a16154f3c",
+   "b55c741df39e4766afd438daa9037b216b7780ad",
    "testharness"
   ],
   "server-timing/navigation_timing_idl.https.html": [
@@ -508367,10 +508503,6 @@
    "0899609e4aeb46463baf719cbeaea50a3523940e",
    "testharness"
   ],
-  "service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt": [
-   "d1a5681d1b3e81bae7c30fe1b8938fd76b35f19d",
-   "support"
-  ],
   "service-workers/service-worker/Service-Worker-Allowed-header.https.html": [
    "9045c0f4e791192c432d99156666292f8df42ab3",
    "testharness"
@@ -508888,7 +509020,7 @@
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-xhr.https-expected.txt": [
-   "44c6a053034ccd646803c60363b9890c4813175f",
+   "a35475540690e3137be8b4f797b6c89eacea7789",
    "support"
   ],
   "service-workers/service-worker/fetch-request-xhr.https.html": [
@@ -516152,7 +516284,7 @@
    "support"
   ],
   "tools/manifest/sourcefile.py": [
-   "800d1f981cc3b8a924351ada9ac303e300546474",
+   "2131c703e04dcbe8de3993df3123d8a342a22e95",
    "support"
   ],
   "tools/manifest/testpaths.py": [
@@ -520516,7 +520648,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/firefox_android.py": [
-   "33b5d51e54e82adb6cdbe4612263bc30883dd108",
+   "fee528071f68843ab056f513295146685f8f78f4",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/ie.py": [
@@ -520584,7 +520716,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executormarionette.py": [
-   "59f7e865a5b8711fa71c9c8955eca731e0048c3f",
+   "01306397db7944cd0dfadf8f1bf0327dbacf94d6",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executoropera.py": [
@@ -520608,7 +520740,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executorwebdriver.py": [
-   "9b5f39764025ebd912f9fd080ad05dd0deea827c",
+   "0b329210fc546f9ee50a8a4d0ae02133e3446106",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executorwebkit.py": [
@@ -520640,7 +520772,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/test-wait.js": [
-   "8a7edb79d62256eef63c71eabd450d42bce7c4d2",
+   "ad08ad7d76fb0299aadedb572193c38c5055e654",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/testharness_servodriver.js": [
@@ -520660,7 +520792,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/font.py": [
-   "6647a8580be7ab4050bbd37593b2e6595bc3ac72",
+   "daf0a1c1bfa221aa47981d93239021e4aefa74a9",
    "support"
   ],
   "tools/wptrunner/wptrunner/formatters/__init__.py": [
@@ -520840,7 +520972,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/wptrunner.py": [
-   "7409dc26560af0be3a397bb73184137d8715811f",
+   "75ce104c7cee335afa2e86592caa2c4caa473bcf",
    "support"
   ],
   "tools/wptrunner/wptrunner/wpttest.py": [
@@ -525984,7 +526116,7 @@
    "testharness"
   ],
   "web-animations/animation-model/animation-types/addition-per-property-expected.txt": [
-   "e86adfcc4b057135aac3056709f1d34083c2582a",
+   "665b9fb2227ee2b685c9e9a0fab39f8702a807aa",
    "support"
   ],
   "web-animations/animation-model/animation-types/addition-per-property.html": [
@@ -526451,6 +526583,38 @@
    "255e013f27a729858310cb545b22d12da283ade5",
    "testharness"
   ],
+  "web-bundle/META.yml": [
+   "0f1912b23a4d109139af314b82263cd31ed8b347",
+   "support"
+  ],
+  "web-bundle/README.md": [
+   "03b42ab340a2c0cdc774b78f203c80d5eee5539f",
+   "support"
+  ],
+  "web-bundle/resources/generate-test-wbns.sh": [
+   "820bb12267c7cd1886d3f9771f24fec46433a370",
+   "support"
+  ],
+  "web-bundle/resources/location/location.html": [
+   "e272dad23da00cfee24c3054c83f48f64fe8d3e2",
+   "support"
+  ],
+  "web-bundle/resources/location/location.js": [
+   "a1dbba73661f87b20895ed90c6cf96451ed5cc1c",
+   "support"
+  ],
+  "web-bundle/resources/wbn/__dir__.headers": [
+   "21e57b9caca1183ecda6f5d4fb9ebd556abf769a",
+   "support"
+  ],
+  "web-bundle/resources/wbn/location.wbn": [
+   "1129cc1e92c89b5b33c86dde61bab7e66c8379bd",
+   "support"
+  ],
+  "web-bundle/wbn-location.tentative.html": [
+   "e0604af6d1e19ac0661e518ba56574a587f3ffc5",
+   "testharness"
+  ],
   "web-locks/META.yml": [
    "24e7d28340606d9a6290af9ceac4f4fb9156abf0",
    "support"
@@ -526588,7 +526752,7 @@
    "manual"
   ],
   "web-nfc/NDEFReader_scan.https.html": [
-   "a9b1d7516173418243c630817eea22fd0bed2046",
+   "17b9fdb8569db230c3a3ded22e0258e4f73a69fc",
    "testharness"
   ],
   "web-nfc/NDEFReader_scan_filter.https-expected.txt": [
@@ -526620,11 +526784,11 @@
    "manual"
   ],
   "web-nfc/NDEFWriter_push.https-expected.txt": [
-   "08edb6f2ee36fc39e80f52b88afeb14a185b0fd7",
+   "7c6b03b096f78c198b0d95dd4f6b87bc62ed011e",
    "support"
   ],
   "web-nfc/NDEFWriter_push.https.html": [
-   "4ff0af8fb0b3947595bdf48015ebabce165003ba",
+   "cb6b3941410035c5c5736e13d59fbbfb85f0d4cc",
    "testharness"
   ],
   "web-nfc/OWNERS": [
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any-expected.txt b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any-expected.txt
new file mode 100644
index 0000000..dd5ffd7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Non-secure context window does not have access to crypto.subtle
+FAIL Non-secure context window does not have access to SubtleCrypto assert_equals: expected (undefined) undefined but got (function) function "function SubtleCrypto() { [native code] }"
+FAIL Non-secure context window does not have access to CryptoKey assert_equals: expected (undefined) undefined but got (function) function "function CryptoKey() { [native code] }"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.js b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.js
new file mode 100644
index 0000000..67ca9d97
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.js
@@ -0,0 +1,18 @@
+// META: global=window,dedicatedworker,sharedworker
+//
+// Do not run this in a service worker as that's always in a secure context
+
+test(() => {
+  assert_equals(self.crypto.subtle, undefined);
+  assert_false("subtle" in self.crypto);
+}, "Non-secure context window does not have access to crypto.subtle");
+
+test(() => {
+  assert_equals(self.SubtleCrypto, undefined);
+  assert_false("SubtleCrypto" in self);
+}, "Non-secure context window does not have access to SubtleCrypto")
+
+test(() => {
+  assert_equals(self.CryptoKey, undefined);
+  assert_false("CryptoKey" in self);
+}, "Non-secure context window does not have access to CryptoKey")
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.sharedworker-expected.txt
new file mode 100644
index 0000000..dd5ffd7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.sharedworker-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Non-secure context window does not have access to crypto.subtle
+FAIL Non-secure context window does not have access to SubtleCrypto assert_equals: expected (undefined) undefined but got (function) function "function SubtleCrypto() { [native code] }"
+FAIL Non-secure context window does not have access to CryptoKey assert_equals: expected (undefined) undefined but got (function) function "function CryptoKey() { [native code] }"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.worker-expected.txt
new file mode 100644
index 0000000..dd5ffd7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/historical.any.worker-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Non-secure context window does not have access to crypto.subtle
+FAIL Non-secure context window does not have access to SubtleCrypto assert_equals: expected (undefined) undefined but got (function) function "function SubtleCrypto() { [native code] }"
+FAIL Non-secure context window does not have access to CryptoKey assert_equals: expected (undefined) undefined but got (function) function "function CryptoKey() { [native code] }"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html
deleted file mode 100644
index 79bcec7..0000000
--- a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-</head>
-<body>
-  <script>
-    async_test(function(t) {
-      assert_true(typeof crypto.subtle === 'undefined');
-      t.done();
-    }, "Non-secure context window does not have access to crypto.subtle");
-    async_test(function(t) {
-      var w = new Worker('../util/worker-report-crypto-subtle-presence.js');
-
-      w.onmessage = t.step_func(function (e) {
-        if (e.data.msg_type == 'subtle_crypto_found') {
-          assert_equals(e.data.msg_value, false);
-          t.done();
-        }
-      });
-
-    }, "Non-secure context worker does not have access to crypto.subtle");
-  </script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/computed-value.html b/third_party/blink/web_tests/external/wpt/css/css-content/computed-value.html
new file mode 100644
index 0000000..505d4b4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-content/computed-value.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: initial computed value of content for elements is not none</title>
+<link rel="help" href="https://drafts.csswg.org/css-content/#content-property">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1605803">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+  assert_equals(getComputedStyle(document.documentElement, "::before").content, "none");
+  assert_not_equals(getComputedStyle(document.documentElement).content, "none");
+}, "initial computed value of content for elements is not none");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/change-intrinsic-width.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/change-intrinsic-width.html
new file mode 100644
index 0000000..3df3e1eb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/change-intrinsic-width.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#pseudo-algorithm">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1037790">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; column-fill:auto; column-gap:0; width:fit-content; height:100px; background:red;">
+  <div id="firstChild" style="width:200px; height:100px; background:green;"></div>
+  <div style="width:50px; height:100px; background:green;"></div>
+</div>
+<script>
+  document.body.offsetTop;
+  firstChild.style.width = "50px";
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/intrinsic-width-change-column-count.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/intrinsic-width-change-column-count.html
new file mode 100644
index 0000000..30e7671
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/intrinsic-width-change-column-count.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#pseudo-algorithm">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1037790">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; background:red;">
+  <div id="container" style="columns:3; column-gap:0; column-fill:auto; width:fit-content; height:100px; background:green;">
+    <div style="width:25px; height:10px;"></div>
+  </div>
+</div>
+<script>
+  document.body.offsetTop;
+  container.style.columns = "4";
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin-ref.html
new file mode 100644
index 0000000..b326c5f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<style>body { margin: 0 }</style>
+<div style="height: 40px"></div>
+<div style="width: 100px; height: 100px; resize: both; overflow: auto; border: 1px solid blue"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin.html b/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin.html
new file mode 100644
index 0000000..a957ac9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/resize-change-margin.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="http://www.w3.org/TR/css3-ui/#resize">
+<link rel="match" href="resize-change-margin-ref.html">
+<style>body { margin: 0 }</style>
+<div id="target" style="width: 100px; height: 100px; resize: both; overflow: auto; border: 1px solid blue"></div>
+<script>
+requestAnimationFrame(() => {
+  requestAnimationFrame(() => {
+    target.style.marginTop = "40px";
+    document.documentElement.classList.remove("reftest-wait");
+  });
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/getClientRects-inline-inline-child.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/getClientRects-inline-inline-child.html
new file mode 100644
index 0000000..9a03ccdb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/getClientRects-inline-inline-child.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/cssom-view-1/#dom-element-getclientrects">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+  <div>
+    <span>test</span>
+    <span id="vertical-align-sub-as-grand-child"
+          title="sub element in a child inline box should not be included">
+      <span>
+        <sub class="not-include" style="vertical-align: sub">subscript</sub>
+      </span>
+    </span>
+    <span>test</span>
+  </div>
+<script>
+testTargetDoesNotInclude('vertical-align-sub-as-grand-child');
+
+function testTargetDoesNotInclude(target) {
+  target = document.getElementById(target);
+  test(() => {
+    let target_rects = target.getClientRects();
+
+    let not_include_rects = [];
+    for (let element of target.querySelectorAll('.not-include')) {
+      for (let rect of element.getClientRects())
+        not_include_rects.push(rect);
+    }
+    for (let rect of target_rects) {
+      for (let not_include_rect of not_include_rects) {
+        assert_rect_not_equals(rect, not_include_rect);
+      }
+    }
+  }, target.title);
+}
+
+function assert_rect_not_equals(rect1, rect2) {
+  assert_false(rectEquals(rect1, rect2),
+               `${rectToString(rect1)} and ${rectToString(rect2)} are not equal`);
+}
+
+function rectEquals(rect1, rect2) {
+  return rect1.x === rect2.x && rect1.y === rect2.y &&
+         rect1.width === rect2.width && rect1.height === rect2.height;
+}
+
+function rectToString(rect) {
+  return `{${rect.x}, ${rect.y} ${rect.width}x${rect.height}}`;
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/dom/historical-expected.txt b/third_party/blink/web_tests/external/wpt/dom/historical-expected.txt
index 2c0959b7..4c0f1de 100644
--- a/third_party/blink/web_tests/external/wpt/dom/historical-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/dom/historical-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 75 tests; 71 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 76 tests; 72 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Historical DOM features must be removed: DOMConfiguration
 PASS Historical DOM features must be removed: DOMCursor
 FAIL Historical DOM features must be removed: DOMError assert_equals: expected (undefined) undefined but got (function) function "function DOMError() { [native code] }"
@@ -33,31 +33,32 @@
 PASS Historical DOM features must be removed: commands
 PASS Historical DOM features must be removed: cssElementMap
 PASS Historical DOM features must be removed: async
+PASS Historical DOM features must be removed: origin
 PASS document.load
 PASS XMLDocument.load
-PASS DOMImplementation.getFeature() must be nuked.
+PASS DOMImplementation.getFeature() must be removed.
 PASS Historical DOM features must be removed: schemaTypeInfo
 PASS Historical DOM features must be removed: setIdAttribute
 PASS Historical DOM features must be removed: setIdAttributeNS
 PASS Historical DOM features must be removed: setIdAttributeNode
-PASS Attr member must be nuked: schemaTypeInfo
-PASS Attr member must be nuked: isId
-PASS DocumentType member must be nuked: entities
-PASS DocumentType member must be nuked: notations
-PASS DocumentType member must be nuked: internalSubset
-PASS Text member must be nuked: isElementContentWhitespace
-PASS Text member must be nuked: replaceWholeText
-PASS Node member must be nuked: hasAttributes
-PASS Node member must be nuked: attributes
-PASS Node member must be nuked: namespaceURI
-PASS Node member must be nuked: prefix
-PASS Node member must be nuked: localName
-PASS Node member must be nuked: isSupported
-PASS Node member must be nuked: getFeature
-PASS Node member must be nuked: getUserData
-PASS Node member must be nuked: setUserData
-PASS Node member must be nuked: rootNode
-PASS Window member must be nuked: attachEvent
+PASS Attr member must be removed: schemaTypeInfo
+PASS Attr member must be removed: isId
+PASS DocumentType member must be removed: entities
+PASS DocumentType member must be removed: notations
+PASS DocumentType member must be removed: internalSubset
+PASS Text member must be removed: isElementContentWhitespace
+PASS Text member must be removed: replaceWholeText
+PASS Node member must be removed: hasAttributes
+PASS Node member must be removed: attributes
+PASS Node member must be removed: namespaceURI
+PASS Node member must be removed: prefix
+PASS Node member must be removed: localName
+PASS Node member must be removed: isSupported
+PASS Node member must be removed: getFeature
+PASS Node member must be removed: getUserData
+PASS Node member must be removed: setUserData
+PASS Node member must be removed: rootNode
+PASS Window member must be removed: attachEvent
 PASS Event should not have this constant: MOUSEDOWN
 PASS Event should not have this constant: MOUSEUP
 PASS Event should not have this constant: MOUSEOVER
diff --git a/third_party/blink/web_tests/external/wpt/dom/historical.html b/third_party/blink/web_tests/external/wpt/dom/historical.html
index 921fa07b..8a71e36 100644
--- a/third_party/blink/web_tests/external/wpt/dom/historical.html
+++ b/third_party/blink/web_tests/external/wpt/dom/historical.html
@@ -1,16 +1,15 @@
 <!DOCTYPE html>
-
 <title>Historical DOM features must be removed</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id=log></div>
 <script>
-function isInterfaceNuked(name) {
+function isInterfaceRemoved(name) {
   test(function() {
     assert_equals(window[name], undefined)
   }, "Historical DOM features must be removed: " + name)
 }
-var nukedInterfaces = [
+var removedInterfaces = [
   "DOMConfiguration",
   "DOMCursor",
   "DOMError",
@@ -31,16 +30,16 @@
   "UserDataHandler",
   "RangeException" // DOM Range
 ]
-nukedInterfaces.forEach(isInterfaceNuked)
+removedInterfaces.forEach(isInterfaceRemoved)
 
-function isNukedFromDocument(name) {
+function isRemovedFromDocument(name) {
   test(function() {
     var doc = document.implementation.createDocument(null,null,null)
     assert_equals(document[name], undefined)
     assert_equals(doc[name], undefined)
   }, "Historical DOM features must be removed: " + name)
 }
-var documentNuked = [
+var documentRemoved = [
   "createEntityReference",
   "xmlEncoding",
   "xmlStandalone",
@@ -58,8 +57,10 @@
   "cssElementMap",
   // https://github.com/whatwg/html/commit/e236f46820b93d6fe2e2caae0363331075c6c4fb
   "async",
+  // https://github.com/whatwg/dom/pull/815
+  "origin",
 ]
-documentNuked.forEach(isNukedFromDocument)
+documentRemoved.forEach(isRemovedFromDocument)
 
 test(function() {
   // https://github.com/whatwg/html/commit/e236f46820b93d6fe2e2caae0363331075c6c4fb
@@ -74,61 +75,61 @@
 
 test(function() {
   assert_equals(document.implementation["getFeature"], undefined)
-}, "DOMImplementation.getFeature() must be nuked.")
+}, "DOMImplementation.getFeature() must be removed.")
 
-function isNukedFromElement(name) {
+function isRemovedFromElement(name) {
   test(function() {
     var ele = document.createElementNS("test", "test")
     assert_equals(document.body[name], undefined)
     assert_equals(ele[name], undefined)
   }, "Historical DOM features must be removed: " + name)
 }
-var elementNuked = [
+var elementRemoved = [
   "schemaTypeInfo",
   "setIdAttribute",
   "setIdAttributeNS",
   "setIdAttributeNode"
 ]
-elementNuked.forEach(isNukedFromElement)
+elementRemoved.forEach(isRemovedFromElement)
 
-function isNukedFromAttr(name) {
+function isRemovedFromAttr(name) {
   test(function() {
     var attr = document.createAttribute("test")
     assert_equals(attr[name], undefined)
-  }, "Attr member must be nuked: " + name)
+  }, "Attr member must be removed: " + name)
 }
-var attrNuked = [
+var attrRemoved = [
   "schemaTypeInfo",
   "isId"
 ]
-attrNuked.forEach(isNukedFromAttr)
+attrRemoved.forEach(isRemovedFromAttr)
 
-function isNukedFromDoctype(name) {
+function isRemovedFromDoctype(name) {
   test(function() {
     var doctype = document.implementation.createDocumentType("test", "", "")
     assert_equals(doctype[name], undefined)
-  }, "DocumentType member must be nuked: " + name)
+  }, "DocumentType member must be removed: " + name)
 }
-var doctypeNuked = [
+var doctypeRemoved = [
   "entities",
   "notations",
   "internalSubset"
 ]
-doctypeNuked.forEach(isNukedFromDoctype)
+doctypeRemoved.forEach(isRemovedFromDoctype)
 
-function isNukedFromText(name) {
+function isRemovedFromText(name) {
   test(function() {
     var text = document.createTextNode("test")
     assert_equals(text[name], undefined)
-  }, "Text member must be nuked: " + name)
+  }, "Text member must be removed: " + name)
 }
-var textNuked = [
+var textRemoved = [
   "isElementContentWhitespace",
   "replaceWholeText"
 ]
-textNuked.forEach(isNukedFromText)
+textRemoved.forEach(isRemovedFromText)
 
-function isNukedFromNode(name) {
+function isRemovedFromNode(name) {
   test(function() {
     var doc = document.implementation.createDocument(null,null,null)
     var doctype = document.implementation.createDocumentType("test", "", "")
@@ -136,9 +137,9 @@
     assert_equals(doc[name], undefined)
     assert_equals(doctype[name], undefined)
     assert_equals(text[name], undefined)
-  }, "Node member must be nuked: " + name)
+  }, "Node member must be removed: " + name)
 }
-var nodeNuked = [
+var nodeRemoved = [
   "hasAttributes",
   "attributes",
   "namespaceURI",
@@ -150,17 +151,17 @@
   "setUserData",
   "rootNode",
 ]
-nodeNuked.forEach(isNukedFromNode)
+nodeRemoved.forEach(isRemovedFromNode)
 
-function isNukedFromWindow(name) {
+function isRemovedFromWindow(name) {
   test(function() {
     assert_equals(window[name], undefined)
-  }, "Window member must be nuked: " + name)
+  }, "Window member must be removed: " + name)
 }
-var windowNuked = [
+var windowRemoved = [
   "attachEvent"
 ]
-windowNuked.forEach(isNukedFromWindow)
+windowRemoved.forEach(isRemovedFromWindow)
 
 function isRemovedFromEvent(name) {
   test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-svg.svg b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-svg.svg
index 28aaf16..77e3d89 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-svg.svg
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-svg.svg
@@ -32,7 +32,6 @@
   assert_equals(doc.compatMode, "CSS1Compat");
   assert_equals(doc.characterSet, "UTF-8");
   assert_equals(doc.contentType, "application/xml");
-  assert_equals(doc.origin, document.origin);
   assert_equals(doc.createElement("DIV").localName, "DIV");
 }, "new Document(): metadata")
 
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-xml.xml b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-xml.xml
index 9aada51..c9fc7758 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-xml.xml
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor-xml.xml
@@ -35,7 +35,6 @@
   assert_equals(doc.compatMode, "CSS1Compat");
   assert_equals(doc.characterSet, "UTF-8");
   assert_equals(doc.contentType, "application/xml");
-  assert_equals(doc.origin, document.origin);
   assert_equals(doc.createElement("DIV").localName, "DIV");
 }, "new Document(): metadata")
 
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor.html b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor.html
index ceb4192..e17de284 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor.html
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-constructor.html
@@ -34,7 +34,6 @@
   assert_equals(doc.compatMode, "CSS1Compat");
   assert_equals(doc.characterSet, "UTF-8");
   assert_equals(doc.contentType, "application/xml");
-  assert_equals(doc.origin, document.origin);
   assert_equals(doc.createElement("DIV").localName, "DIV");
   assert_equals(doc.createElement("a").constructor, Element);
 }, "new Document(): metadata")
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Node-appendChild-cereactions-vs-script.window.js b/third_party/blink/web_tests/external/wpt/dom/nodes/Node-appendChild-cereactions-vs-script.window.js
new file mode 100644
index 0000000..bc0b8ad
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Node-appendChild-cereactions-vs-script.window.js
@@ -0,0 +1,27 @@
+const results = [];
+test(() => {
+  class Script1 extends HTMLScriptElement {
+    constructor() {
+      super();
+    }
+    connectedCallback() {
+      results.push("ce connected s1");
+    }
+  }
+  class Script2 extends HTMLScriptElement {
+    constructor() {
+      super();
+    }
+    connectedCallback() {
+      results.push("ce connected s2");
+    }
+  }
+  customElements.define("script-1", Script1, { extends: "script" });
+  customElements.define("script-2", Script2, { extends: "script" });
+  const s1 = new Script1();
+  s1.textContent = "results.push('s1')";
+  const s2 = new Script2();
+  s2.textContent = "results.push('s2')";
+  document.body.append(s1, s2);
+  assert_array_equals(results, ["s1", "s2", "ce connected s1", "ce connected s2"]);
+}, "Custom element reactions follow script execution");
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Node-cloneNode.html b/third_party/blink/web_tests/external/wpt/dom/nodes/Node-cloneNode.html
index 08d620b..d977b2a 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Node-cloneNode.html
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Node-cloneNode.html
@@ -240,7 +240,6 @@
     assert_equals(doc.contentType, copy.contentType, "contentType equality");
     assert_equals(doc.URL, "about:blank", "URL value")
     assert_equals(doc.URL, copy.URL, "URL equality");
-    assert_equals(doc.origin, copy.origin, "origin equality");
     assert_equals(doc.compatMode, "CSS1Compat", "compatMode value");
     assert_equals(doc.compatMode, copy.compatMode, "compatMode equality");
 }, "implementation.createDocument");
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/windows/browsing-context.html b/third_party/blink/web_tests/external/wpt/html/browsers/windows/browsing-context.html
index 5e99bb5..430598f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/windows/browsing-context.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/windows/browsing-context.html
@@ -40,7 +40,6 @@
     }, "Check that new document nodes extant, empty");
 
     test(function () {
-      assert_equals(doc.origin, document.origin, "The document's origin should be its creator document's origin");
       assert_equals(doc.referrer, document.URL, "The document's referrer should be its creator document's address.");
       assert_equals(iframe.contentWindow.parent.document, document);
     }, "Check the document properties corresponding to the creator browsing context");
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/none.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/none.https.html
index f13a752..7f296e6 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/none.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/none.https.html
@@ -41,13 +41,13 @@
   const w = window.open(`resources/navigate-none.sub.html?to=navigate-require-corp.sub.html`, "window_name");
   t.add_cleanup(() => w.close());
 
-  t.step_timeout(() => {
+  w.onload = t.step_func(() => {
     w.history.back();
     t.step_timeout(() => {
       assert_not_equals(w.document, null);
       t.done();
-    }, 500);
-  }, 500);
+    }, 1500);
+  });
 }, `"none" top-level: navigating a frame back from "require-corp" should succeed`);
 
 async_test(t => {
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/usvstring-reflection.https.html b/third_party/blink/web_tests/external/wpt/html/dom/usvstring-reflection.https.html
index 162d58c..d3c90e5 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/usvstring-reflection.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/dom/usvstring-reflection.https.html
@@ -118,9 +118,6 @@
   var w = window.open("about:blank#\uD800");
   assert_equals(w.document.URL, 'about:blank#%EF%BF%BD');
   assert_equals(w.document.documentURI, 'about:blank#%EF%BF%BD');
-  // TODO(gyuyoung): How to test document.origin? When opening a URL with an
-  // unpaired surrogate codepoint, invalid URL exception happens.
-  //   e.g) var w = window.open("http://test.com\uDB89");
 }, "Document URLs: unpaired surrogate codepoint should be replaced with U+FFFD")
 
 promise_test(t => {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt
index e1bb6e4..b0da383 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt
@@ -1,46 +1,46 @@
 This is a testharness.js-based test.
 PASS [INPUT in TEXT status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in TEXT status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in TEXT status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in SEARCH status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in SEARCH status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in SEARCH status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in TEL status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in TEL status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in TEL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in PASSWORD status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in PASSWORD status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in PASSWORD status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in URL status] validity.valid must be false if validity.patternMismatch is true
 PASS [INPUT in URL status] validity.valid must be false if validity.typeMismatch is true
-PASS [INPUT in URL status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in URL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in EMAIL status] validity.valid must be false if validity.patternMismatch is true
 PASS [INPUT in EMAIL status] validity.valid must be false if validity.typeMismatch is true
-PASS [INPUT in EMAIL status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in EMAIL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in DATE status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in DATE status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in DATE status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in DATE status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in DATE status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in MONTH status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in MONTH status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in MONTH status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in MONTH status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in MONTH status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in WEEK status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in WEEK status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in WEEK status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in WEEK status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in WEEK status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in TIME status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in TIME status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in TIME status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in TIME status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in TIME status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in NUMBER status] validity.valid must be false if validity.rangeOverflow is true
 PASS [INPUT in NUMBER status] validity.valid must be false if validity.rangeUnderflow is true
 PASS [INPUT in NUMBER status] validity.valid must be false if validity.stepMismatch is true
-PASS [INPUT in NUMBER status] validity.valid must be false if validity.valueMissing is true
+FAIL [INPUT in NUMBER status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 PASS [INPUT in CHECKBOX status] validity.valid must be false if validity.valueMissing is true
 FAIL [INPUT in RADIO status] validity.valid must be false if validity.valueMissing is true assert_false: The validity.valid should be false. expected false got true
 PASS [INPUT in FILE status] validity.valid must be false if validity.valueMissing is true
 PASS [select]  validity.valid must be false if validity.valueMissing is true
-PASS [textarea]  validity.valid must be false if validity.valueMissing is true
+FAIL [textarea]  validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid.html
index cec5dcb..03655ff 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid.html
@@ -15,7 +15,7 @@
       types: ["text", "search", "tel", "password"],
       testData: [
         {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -24,7 +24,7 @@
       testData: [
         {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
         {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -33,7 +33,7 @@
       testData: [
         {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
         {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -43,7 +43,7 @@
         {conditions: {max: "2000-01-01T12:00:00", value: "2001-01-01T12:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
         {conditions: {min: "2001-01-01T12:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -53,7 +53,7 @@
         {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
         {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         {conditions: {step: 2 * 1 * 86400000, value: "2000-01-03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -64,7 +64,7 @@
         {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         // Step checks that "months since Jan 1970" is evenly divisible by `step`
         {conditions: {step: 3, value: "2001-02"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -74,7 +74,7 @@
         {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
         {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -84,7 +84,7 @@
         {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
         {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -94,7 +94,7 @@
         {conditions: {max: "5", value: "6"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
         {conditions: {min: "5", value: "4"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
         {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     },
     {
@@ -122,7 +122,7 @@
       tag: "textarea",
       types: [],
       testData: [
-        {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+        {conditions: {required: true, value: ""}, expected: false, expectedImmutable: true, name: "[target] validity.valid must be false if validity.valueMissing is true"}
       ]
     }
   ];
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
index 611137c81..b4497dd 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
@@ -1,85 +1,85 @@
 This is a testharness.js-based test.
-Found 94 tests; 91 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 94 tests; 48 PASS, 46 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [INPUT in TEXT status] The required attribute is not set
 PASS [INPUT in TEXT status] The value is not empty and required is true
-PASS [INPUT in TEXT status] The value is empty and required is true
+FAIL [INPUT in TEXT status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in SEARCH status] The required attribute is not set
 PASS [INPUT in SEARCH status] The value is not empty and required is true
-PASS [INPUT in SEARCH status] The value is empty and required is true
+FAIL [INPUT in SEARCH status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in TEL status] The required attribute is not set
 PASS [INPUT in TEL status] The value is not empty and required is true
-PASS [INPUT in TEL status] The value is empty and required is true
+FAIL [INPUT in TEL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in URL status] The required attribute is not set
 PASS [INPUT in URL status] The value is not empty and required is true
-PASS [INPUT in URL status] The value is empty and required is true
+FAIL [INPUT in URL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in EMAIL status] The required attribute is not set
 PASS [INPUT in EMAIL status] The value is not empty and required is true
-PASS [INPUT in EMAIL status] The value is empty and required is true
+FAIL [INPUT in EMAIL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in PASSWORD status] The required attribute is not set
 PASS [INPUT in PASSWORD status] The value is not empty and required is true
-PASS [INPUT in PASSWORD status] The value is empty and required is true
+FAIL [INPUT in PASSWORD status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in DATETIME-LOCAL status] The required attribute is not set
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10T12:00:00)
 FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00) assert_false: The validity.valueMissing should be false. expected false got true
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14T12:00:00.001)
-PASS [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567)
-PASS [INPUT in DATETIME-LOCAL status] The value attribute is a Date object
-PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99)
+FAIL [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATETIME-LOCAL status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00) assert_false: The validity.valueMissing should be false. expected false got true
-PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space
-PASS [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc)
-PASS [INPUT in DATETIME-LOCAL status] The value attribute is empty string
+FAIL [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATETIME-LOCAL status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in DATE status] The required attribute is not set
 PASS [INPUT in DATE status] Valid date string(2000-12-10)
 PASS [INPUT in DATE status] Valid date string(9999-01-01)
-PASS [INPUT in DATE status] The value attribute is a number(1234567)
-PASS [INPUT in DATE status] The value attribute is a Date object
-PASS [INPUT in DATE status] Invalid date string(9999-99-99)
-PASS [INPUT in DATE status] Invalid date string(37-01-01)
-PASS [INPUT in DATE status] Invalid date string(2000/01/01)
-PASS [INPUT in DATE status] The value attribute is empty string
+FAIL [INPUT in DATE status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATE status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATE status] Invalid date string(9999-99-99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATE status] Invalid date string(37-01-01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATE status] Invalid date string(2000/01/01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in DATE status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in MONTH status] The required attribute is not set
 PASS [INPUT in MONTH status] Valid month string(2000-12)
 PASS [INPUT in MONTH status] Valid month string(9999-01)
-PASS [INPUT in MONTH status] The value attribute is a number(1234567)
-PASS [INPUT in MONTH status] The value attribute is a Date object
-PASS [INPUT in MONTH status] Invalid month string(2000-99)
-PASS [INPUT in MONTH status] Invalid month string(37-01)
-PASS [INPUT in MONTH status] Invalid month string(2000/01)
-PASS [INPUT in MONTH status] The value attribute is empty string
+FAIL [INPUT in MONTH status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in MONTH status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in MONTH status] Invalid month string(2000-99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in MONTH status] Invalid month string(37-01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in MONTH status] Invalid month string(2000/01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in MONTH status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in WEEK status] The required attribute is not set
 PASS [INPUT in WEEK status] Valid week string(2000-W12)
 PASS [INPUT in WEEK status] Valid week string(9999-W01)
-PASS [INPUT in WEEK status] The value attribute is a number(1234567)
-PASS [INPUT in WEEK status] The value attribute is a Date object
-PASS [INPUT in WEEK status] Invalid week string(2000-W99)
-PASS [INPUT in WEEK status] invalid week string(2000-W00)
-PASS [INPUT in WEEK status] invalid week string(2000-w01)
-PASS [INPUT in WEEK status] The value attribute is empty string
+FAIL [INPUT in WEEK status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in WEEK status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in WEEK status] Invalid week string(2000-W99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in WEEK status] invalid week string(2000-W00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in WEEK status] invalid week string(2000-w01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in WEEK status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in TIME status] The required attribute is not set
 PASS [INPUT in TIME status] Validtime string(12:00:00)
 PASS [INPUT in TIME status] Validtime string(12:00)
 PASS [INPUT in TIME status] Valid time string(12:00:60.001)
 PASS [INPUT in TIME status] Valid time string(12:00:60.01)
 PASS [INPUT in TIME status] Valid time string(12:00:60.1)
-PASS [INPUT in TIME status] The value attribute is a number(1234567)
-PASS [INPUT in TIME status] The value attribute is a time object
-PASS [INPUT in TIME status] Invalid time string(25:00:00)
-PASS [INPUT in TIME status] Invalid time string(12:60:00)
-PASS [INPUT in TIME status] Invalid time string(12:00:60)
-PASS [INPUT in TIME status] Invalid time string(12:00:00:001)
-PASS [INPUT in TIME status] The value attribute is empty string
+FAIL [INPUT in TIME status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] The value attribute is a time object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] Invalid time string(25:00:00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] Invalid time string(12:60:00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] Invalid time string(12:00:60) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] Invalid time string(12:00:00:001) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in TIME status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in NUMBER status] The required attribute is not set
 PASS [INPUT in NUMBER status] Value is an integer with a leading symbol '+'
 PASS [INPUT in NUMBER status] Value is a number with a '-' symbol
 PASS [INPUT in NUMBER status] Value is a number in scientific notation form(e is in lowercase)
 PASS [INPUT in NUMBER status] Value is a number in scientific notation form(E is in uppercase)
 PASS [INPUT in NUMBER status] Value is -0
-PASS [INPUT in NUMBER status] Value is a number with some white spaces
-PASS [INPUT in NUMBER status] Value is Math.pow(2, 1024)
-PASS [INPUT in NUMBER status] Value is Math.pow(-2, 1024)
-PASS [INPUT in NUMBER status] Value is a string that cannot be converted to a number
-PASS [INPUT in NUMBER status] The value attribute is empty string
+FAIL [INPUT in NUMBER status] Value is a number with some white spaces assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in NUMBER status] Value is Math.pow(2, 1024) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in NUMBER status] Value is Math.pow(-2, 1024) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in NUMBER status] Value is a string that cannot be converted to a number assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+FAIL [INPUT in NUMBER status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 PASS [INPUT in CHECKBOX status] The required attribute is not set
 PASS [INPUT in CHECKBOX status] The checked attribute is true
 PASS [INPUT in CHECKBOX status] The checked attribute is false
@@ -93,6 +93,6 @@
 PASS [select]  Selected the option with value equals to empty
 PASS [textarea]  The required attribute is not set
 PASS [textarea]  The value is not empty
-PASS [textarea]  The value is empty
+FAIL [textarea]  The value is empty assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
index 3c9e4c4..2e1c666 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
@@ -16,7 +16,7 @@
       testData: [
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty and required is true"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value is empty and required is true"}
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value is empty and required is true"}
       ]
     },
     {
@@ -27,13 +27,13 @@
         {conditions: {required: true, value: "2000-12-10T12:00:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10T12:00:00)"},
         {conditions: {required: true, value: "2000-12-10 12:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10 12:00)"},
         {conditions: {required: true, value: "1979-10-14T12:00:00.001"}, expected: false, name: "[target] Valid local date and time string(1979-10-14T12:00:00.001)"},
-        {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
-        {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
-        {conditions: {required: true, value: "1979-10-99 99:99"}, expected: true, name: "[target] Invalid local date and time string(1979-10-99 99:99)"},
+        {conditions: {required: true, value: 1234567}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a number(1234567)"},
+        {conditions: {required: true, value: new Date()}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a Date object"},
+        {conditions: {required: true, value: "1979-10-99 99:99"}, expected: true, expectedImmutable: false, name: "[target] Invalid local date and time string(1979-10-99 99:99)"},
         {conditions: {required: true, value: "1979-10-14 12:00:00"}, expected: false, name: "[target] Valid local date and time string(1979-10-14 12:00:00)"},
-        {conditions: {required: true, value: "2001-12-21  12:00"}, expected: true, name: "[target] Invalid local date and time string(2001-12-21  12:00)-two white space"},
-        {conditions: {required: true, value: "abc"}, expected: true, name: "[target] the value attribute is a string(abc)"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: "2001-12-21  12:00"}, expected: true, expectedImmutable: false, name: "[target] Invalid local date and time string(2001-12-21  12:00)-two white space"},
+        {conditions: {required: true, value: "abc"}, expected: true, expectedImmutable: false, name: "[target] the value attribute is a string(abc)"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -43,12 +43,12 @@
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "2000-12-10"}, expected: false, name: "[target] Valid date string(2000-12-10)"},
         {conditions: {required: true, value: "9999-01-01"}, expected: false, name: "[target] Valid date string(9999-01-01)"},
-        {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
-        {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
-        {conditions: {required: true, value: "9999-99-99"}, expected: true, name: "[target] Invalid date string(9999-99-99)"},
-        {conditions: {required: true, value: "37/01/01"}, expected: true, name: "[target] Invalid date string(37-01-01)"},
-        {conditions: {required: true, value: "2000/01/01"}, expected: true, name: "[target] Invalid date string(2000/01/01)"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: 1234567}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a number(1234567)"},
+        {conditions: {required: true, value: new Date()}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a Date object"},
+        {conditions: {required: true, value: "9999-99-99"}, expected: true, expectedImmutable: false, name: "[target] Invalid date string(9999-99-99)"},
+        {conditions: {required: true, value: "37/01/01"}, expected: true, expectedImmutable: false, name: "[target] Invalid date string(37-01-01)"},
+        {conditions: {required: true, value: "2000/01/01"}, expected: true, expectedImmutable: false, name: "[target] Invalid date string(2000/01/01)"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -58,12 +58,12 @@
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "2000-12"}, expected: false, name: "[target] Valid month string(2000-12)"},
         {conditions: {required: true, value: "9999-01"}, expected: false, name: "[target] Valid month string(9999-01)"},
-        {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
-        {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
-        {conditions: {required: true, value: "2000-99"}, expected: true, name: "[target] Invalid month string(2000-99)"},
-        {conditions: {required: true, value: "37-01"}, expected: true, name: "[target] Invalid month string(37-01)"},
-        {conditions: {required: true, value: "2000/01"}, expected: true, name: "[target] Invalid month string(2000/01)"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: 1234567}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a number(1234567)"},
+        {conditions: {required: true, value: new Date()}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a Date object"},
+        {conditions: {required: true, value: "2000-99"}, expected: true, expectedImmutable: false, name: "[target] Invalid month string(2000-99)"},
+        {conditions: {required: true, value: "37-01"}, expected: true, expectedImmutable: false, name: "[target] Invalid month string(37-01)"},
+        {conditions: {required: true, value: "2000/01"}, expected: true, expectedImmutable: false, name: "[target] Invalid month string(2000/01)"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -73,12 +73,12 @@
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "2000-W12"}, expected: false, name: "[target] Valid week string(2000-W12)"},
         {conditions: {required: true, value: "9999-W01"}, expected: false, name: "[target] Valid week string(9999-W01)"},
-        {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
-        {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
-        {conditions: {required: true, value: "2000-W99"}, expected: true, name: "[target] Invalid week string(2000-W99)"},
-        {conditions: {required: true, value: "2000-W00"}, expected: true, name: "[target] invalid week string(2000-W00)"},
-        {conditions: {required: true, value: "2000-w01"}, expected: true, name: "[target] invalid week string(2000-w01)"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: 1234567}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a number(1234567)"},
+        {conditions: {required: true, value: new Date()}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a Date object"},
+        {conditions: {required: true, value: "2000-W99"}, expected: true, expectedImmutable: false, name: "[target] Invalid week string(2000-W99)"},
+        {conditions: {required: true, value: "2000-W00"}, expected: true, expectedImmutable: false, name: "[target] invalid week string(2000-W00)"},
+        {conditions: {required: true, value: "2000-w01"}, expected: true, expectedImmutable: false, name: "[target] invalid week string(2000-w01)"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -91,13 +91,13 @@
         {conditions: {required: true, value: "12:00:00.001"}, expected: false, name: "[target] Valid time string(12:00:60.001)"},
         {conditions: {required: true, value: "12:00:00.01"}, expected: false, name: "[target] Valid time string(12:00:60.01)"},
         {conditions: {required: true, value: "12:00:00.1"}, expected: false, name: "[target] Valid time string(12:00:60.1)"},
-        {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
-        {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a time object"},
-        {conditions: {required: true, value: "25:00:00"}, expected: true, name: "[target] Invalid time string(25:00:00)"},
-        {conditions: {required: true, value: "12:60:00"}, expected: true, name: "[target] Invalid time string(12:60:00)"},
-        {conditions: {required: true, value: "12:00:60"}, expected: true, name: "[target] Invalid time string(12:00:60)"},
-        {conditions: {required: true, value: "12:00:00:001"}, expected: true, name: "[target] Invalid time string(12:00:00:001)"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: 1234567}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a number(1234567)"},
+        {conditions: {required: true, value: new Date()}, expected: true, expectedImmutable: false, name: "[target] The value attribute is a time object"},
+        {conditions: {required: true, value: "25:00:00"}, expected: true, expectedImmutable: false, name: "[target] Invalid time string(25:00:00)"},
+        {conditions: {required: true, value: "12:60:00"}, expected: true, expectedImmutable: false, name: "[target] Invalid time string(12:60:00)"},
+        {conditions: {required: true, value: "12:00:60"}, expected: true, expectedImmutable: false, name: "[target] Invalid time string(12:00:60)"},
+        {conditions: {required: true, value: "12:00:00:001"}, expected: true, expectedImmutable: false, name: "[target] Invalid time string(12:00:00:001)"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -110,11 +110,11 @@
         {conditions: {required: true, value: "123.01e-10"}, expected: false, name: "[target] Value is a number in scientific notation form(e is in lowercase)"},
         {conditions: {required: true, value: "123.01E+10"}, expected: false, name: "[target] Value is a number in scientific notation form(E is in uppercase)"},
         {conditions: {required: true, value: "-0"}, expected: false, name: "[target] Value is -0"},
-        {conditions: {required: true, value: " 123 "}, expected: true, name: "[target] Value is a number with some white spaces"},
-        {conditions: {required: true, value: Math.pow(2, 1024)}, expected: true, name: "[target] Value is Math.pow(2, 1024)"},
-        {conditions: {required: true, value: Math.pow(-2, 1024)}, expected: true, name: "[target] Value is Math.pow(-2, 1024)"},
-        {conditions: {required: true, value: "abc"}, expected: true, name: "[target] Value is a string that cannot be converted to a number"},
-        {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+        {conditions: {required: true, value: " 123 "}, expected: true, expectedImmutable: false, name: "[target] Value is a number with some white spaces"},
+        {conditions: {required: true, value: Math.pow(2, 1024)}, expected: true, expectedImmutable: false, name: "[target] Value is Math.pow(2, 1024)"},
+        {conditions: {required: true, value: Math.pow(-2, 1024)}, expected: true, expectedImmutable: false, name: "[target] Value is Math.pow(-2, 1024)"},
+        {conditions: {required: true, value: "abc"}, expected: true, expectedImmutable: false, name: "[target] Value is a string that cannot be converted to a number"},
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value attribute is empty string"}
       ]
     },
     {
@@ -159,7 +159,7 @@
       testData: [
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty"},
-        {conditions: {required: true, value: ""}, expected: true  , name: "[target] The value is empty"}
+        {conditions: {required: true, value: ""}, expected: true, expectedImmutable: false, name: "[target] The value is empty"}
       ]
     }
   ];
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate-expected.txt
new file mode 100644
index 0000000..67281aa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate-expected.txt
@@ -0,0 +1,77 @@
+This is a testharness.js-based test.
+Found 73 tests; 70 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS [INPUT in HIDDEN status] Must be barred from the constraint validation
+PASS [INPUT in BUTTON status] Must be barred from the constraint validation
+PASS [INPUT in RESET status] Must be barred from the constraint validation
+PASS [BUTTON in BUTTON status] Must be barred from the constraint validation
+PASS [BUTTON in RESET status] Must be barred from the constraint validation
+PASS [fieldset]  The willValidate attribute must be false since FIELDSET is not a submittable element
+PASS [output]  The willValidate attribute must be false since OUTPUT is not a submittable element
+PASS [object]  Must be barred from the constraint validation
+PASS [INPUT in TEXT status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in TEXT status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in TEXT status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in TEXT status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in SEARCH status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in SEARCH status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in SEARCH status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in SEARCH status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in TEL status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in TEL status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in TEL status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in TEL status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in URL status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in URL status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in URL status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in URL status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in EMAIL status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in EMAIL status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in EMAIL status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in EMAIL status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in PASSWORD status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in PASSWORD status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in PASSWORD status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in PASSWORD status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in DATETIME-LOCAL status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in DATETIME-LOCAL status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in DATETIME-LOCAL status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in DATETIME-LOCAL status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in DATE status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in DATE status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in DATE status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in DATE status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in MONTH status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in MONTH status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in MONTH status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in MONTH status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in WEEK status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in WEEK status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in WEEK status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in WEEK status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in TIME status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in TIME status] The willValidate attribute must be true if an element is mutable
+PASS [INPUT in TIME status] Must be barred from the constraint validation if it is readonly
+PASS [INPUT in TIME status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in COLOR status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in COLOR status] The willValidate attribute must be true if an element is mutable
+FAIL [INPUT in COLOR status] Must be not barred from the constraint validation even if it is readonly assert_true: The willValidate attribute should be true. expected true got false
+PASS [INPUT in COLOR status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in FILE status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in FILE status] The willValidate attribute must be true if an element is mutable
+FAIL [INPUT in FILE status] Must be not barred from the constraint validation even if it is readonly assert_true: The willValidate attribute should be true. expected true got false
+PASS [INPUT in FILE status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [INPUT in SUBMIT status] Must be barred from the constraint validation if it is disabled
+PASS [INPUT in SUBMIT status] The willValidate attribute must be true if an element is mutable
+FAIL [INPUT in SUBMIT status] Must be not barred from the constraint validation even if it is readonly assert_true: The willValidate attribute should be true. expected true got false
+PASS [INPUT in SUBMIT status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [BUTTON in SUBMIT status] Must be barred from the constraint validation
+PASS [BUTTON in SUBMIT status] The willValidate attribute must be true if an element is mutable
+PASS [BUTTON in SUBMIT status] The willValidate attribute must be false if it has a datalist ancestor
+PASS [select]  Must be barred from the constraint validation
+PASS [select]  The willValidate attribute must be true if an element is mutable
+PASS [select]  The willValidate attribute must be false if it has a datalist ancestor
+PASS [textarea]  Must be barred from the constraint validation
+PASS [textarea]  The willValidate attribute must be true if an element is mutable
+PASS [textarea]  The willValidate attribute must be false if it has a datalist ancestor
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate.html
index 6c66559..ccd1cf0 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-willValidate.html
@@ -41,10 +41,11 @@
     },
     //If an element is disabled, it is barred from constraint validation.
     //The willValidate attribute must be true if an element is mutable
-    //If the readonly attribute is specified on an INPUT element, the element is barred from constraint validation.
+    //If the readonly attribute is specified on an INPUT element, the element is barred from constraint validation
+    //(with the assumption that the readonly attribute applies).
     {
       tag: "input",
-      types: ["text", "search", "tel", "url", "email", "password", "datetime-local", "date", "month", "week", "time", "color", "file", "submit"],
+      types: ["text", "search", "tel", "url", "email", "password", "datetime-local", "date", "month", "week", "time"],
       testData: [
         {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is disabled"},
         {conditions: {disabled: false, readOnly: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
@@ -52,6 +53,17 @@
         {conditions: {disabled: false, readOnly: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"},
       ]
     },
+    //In the following cases, the readonly attribute does not apply.
+    {
+      tag: "input",
+      types: ["color", "file", "submit"],
+      testData: [
+        {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is disabled"},
+        {conditions: {disabled: false, readOnly: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
+        {conditions: {readOnly: true}, expected: true, name: "[target] Must be not barred from the constraint validation even if it is readonly"},
+        {conditions: {disabled: false, readOnly: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"},
+      ]
+    },
     {
       tag: "button",
       types: ["submit"],
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/support/validator.js b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/support/validator.js
index 48c3a5b..33508fb 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/support/validator.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/support/validator.js
@@ -5,8 +5,8 @@
     test(function() {
       self.pre_check(ctl, 'tooLong');
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.tooLong,
               'The validity.tooLong should be true' + condStr);
@@ -23,8 +23,8 @@
     test(function () {
       self.pre_check(ctl, "tooShort");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.tooShort,
               'The validity.tooShort should be true' + condStr);
@@ -41,8 +41,8 @@
     test(function () {
       self.pre_check(ctl, "patternMismatch");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.patternMismatch,
               'The validity.patternMismatch should be true' + condStr);
@@ -59,8 +59,8 @@
     test(function () {
       self.pre_check(ctl, "valueMissing");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.valueMissing,
               'The validity.valueMissing should be true' + condStr);
@@ -77,8 +77,8 @@
     test(function () {
       self.pre_check(ctl, "typeMismatch");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.typeMismatch,
               'The validity.typeMismatch should be true' + condStr);
@@ -95,8 +95,8 @@
     test(function () {
       self.pre_check(ctl, "rangeOverflow");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.rangeOverflow,
               'The validity.rangeOverflow should be true' + condStr);
@@ -113,8 +113,8 @@
     test(function () {
       self.pre_check(ctl, "rangeUnderflow");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.rangeUnderflow,
               'The validity.rangeUnderflow should be true' + condStr);
@@ -131,8 +131,8 @@
     test(function () {
       self.pre_check(ctl, "stepMismatch");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.stepMismatch,
               'The validity.stepMismatch should be true' + condStr);
@@ -149,8 +149,8 @@
     test(function () {
       self.pre_check(ctl, "badInput");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.badInput,
               'The validity.badInput should be true' + condStr);
@@ -167,14 +167,14 @@
     test(function () {
       self.pre_check(ctl, "customError");
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected) {
+        const {ctl, expected, condStr} = val;
+        if (expected) {
           assert_true(
               ctl.validity.customError,
               'The validity.customError attribute should be true' + condStr);
           // validationMessage returns the empty string if ctl is barred from
-          // constraint validation, which happens if ctl is disabled.
-          if (ctl.disabled) {
+          // constraint validation, which happens if ctl is disabled or readOnly.
+          if (ctl.disabled || ctl.readOnly) {
             assert_equals(
                 ctl.validationMessage, '',
                 'The validationMessage attribute must be empty' + condStr);
@@ -200,8 +200,8 @@
     var self = this;
     test(function () {
       self.iterate_over(ctl, data).forEach(function(val) {
-        const {ctl, data, condStr} = val;
-        if (data.expected)
+        const {ctl, expected, condStr} = val;
+        if (expected)
           assert_true(
               ctl.validity.valid,
               'The validity.valid should be true' + condStr);
@@ -389,39 +389,54 @@
   },
 
   iterate_over: function(ctl, data) {
-    // Iterate over normal, disabled, readonly, and both.
+    // Iterate over normal, disabled, readonly, and both (if applicable).
+    var ctlNormal = ctl.cloneNode(true);
+    this.set_conditions(ctlNormal, data.conditions);
+    if (data.dirty)
+      this.set_dirty(ctlNormal);
+
     var ctlDisabled = ctl.cloneNode(true);
     this.set_conditions(ctlDisabled, data.conditions);
     if (data.dirty)
       this.set_dirty(ctlDisabled);
     ctlDisabled.disabled = true;
 
-    var ctlReadonly = ctl.cloneNode(true);
-    this.set_conditions(ctlReadonly, data.conditions);
-    if (data.dirty)
-      this.set_dirty(ctlReadonly);
-    ctlReadonly.readonly = true;
+    var expectedImmutable =
+      data.expectedImmutable !== undefined ? data.expectedImmutable : data.expected;
 
-    var ctlBoth = ctl.cloneNode(true);
-    this.set_conditions(ctlBoth, data.conditions);
-    if (data.dirty)
-      this.set_dirty(ctlBoth);
-    ctlBoth.disabled = true;
-    ctlBoth.readonly = true;
+    var variants = [
+      {ctl: ctlNormal, expected: data.expected, condStr: '.'},
+      {ctl: ctlDisabled, expected: expectedImmutable, condStr: ', when control is disabled.'},
+    ];
 
-    ctl = ctl.cloneNode(true);
-    this.set_conditions(ctl, data.conditions);
+    if ('readOnly' in ctl) {
+      var ctlReadonly = ctl.cloneNode(true);
+      this.set_conditions(ctlReadonly, data.conditions);
+      if (data.dirty)
+        this.set_dirty(ctlReadonly);
+      ctlReadonly.readOnly = true;
 
-    return [
-      {ctl: ctl, data: data, condStr: '.'},
-      {ctl: ctlDisabled, data: data, condStr: ', when control is disabled.'},
-      {ctl: ctlReadonly, data: data, condStr: ', when control is readonly.'},
-      {
+      var ctlBoth = ctl.cloneNode(true);
+      this.set_conditions(ctlBoth, data.conditions);
+      if (data.dirty)
+        this.set_dirty(ctlBoth);
+      ctlBoth.disabled = true;
+      ctlBoth.readOnly = true;
+
+      variants.push({
+        ctl: ctlReadonly,
+        expected: expectedImmutable,
+        condStr: ', when control is readonly.'
+      });
+
+      variants.push({
         ctl: ctlBoth,
-        data: data,
+        expected: expectedImmutable,
         condStr: ', when control is disabled & readonly.'
-      },
-    ]
+      });
+    }
+
+    return variants;
   },
 
   run_test: function(testee, method) {
diff --git a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas-expected.txt b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas-expected.txt
deleted file mode 100644
index 8a5d001..0000000
--- a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test that ctx.canvas on a ImageBitmapRenderingContext returns the original canvas assert_object_equals: unexpected property "width"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas.html b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas.html
index 9c3a1fb..b0753a7 100644
--- a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas.html
+++ b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/context-preserves-canvas.html
@@ -5,19 +5,18 @@
 <script src="/resources/testharnessreport.js"></script>
 <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#the-imagebitmap-rendering-context">
 <script>
-var width = 10;
-var height = 10;
-
 test(function() {
+    var width = 10;
+    var height = 10;
     var canvas = document.createElement("canvas");
     canvas.width = width;
     canvas.height = height;
     var ctx = canvas.getContext('bitmaprenderer');
     var dstCanvas = ctx.canvas;
     assert_true("canvas" in ctx);
-    assert_object_equals(canvas, ctx.canvas);
+    assert_equals(dstCanvas, ctx.canvas);
+    assert_equals(canvas, ctx.canvas);
     assert_equals(dstCanvas.width, width);
     assert_equals(dstCanvas.height, height);
 }, "Test that ctx.canvas on a ImageBitmapRenderingContext returns the original canvas");
-
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/lint.whitelist b/third_party/blink/web_tests/external/wpt/lint.whitelist
index b5a8f806..6264476 100644
--- a/third_party/blink/web_tests/external/wpt/lint.whitelist
+++ b/third_party/blink/web_tests/external/wpt/lint.whitelist
@@ -691,6 +691,10 @@
 WEB-PLATFORM.TEST:signed-exchange/appcache/resources/*.sxg
 WEB-PLATFORM.TEST:signed-exchange/resources/generate-test-sxgs.sh
 
+# Web Bundle files have hard-coded URLs
+WEB-PLATFORM.TEST:web-bundle/resources/generate-test-wbns.sh
+WEB-PLATFORM.TEST:web-bundle/resources/wbn/*.wbn
+
 # Tests that depend on resources in /gen/ in Chromium:
 # https://github.com/web-platform-tests/wpt/issues/16455
 # Please consult with ecosystem-infra@chromium.org before adding more.
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js b/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
index 8cc3546b..2ec9c75 100644
--- a/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
+++ b/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
@@ -6,8 +6,8 @@
 // http://www.w3.org/TR/navigation-timing/
 
 idl_test(
-  ['navigation-timing'],
-  ['resource-timing', 'performance-timeline', 'hr-time', 'dom'],
+  ['hr-time', 'navigation-timing'],
+  ['resource-timing', 'performance-timeline', 'html', 'dom'],
   idl_array => {
     idl_array.add_objects({
       Performance: ['performance'],
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
index 4bafc9b..2c1724b 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
@@ -170,6 +170,7 @@
       this.reading_messages_ = [];
       this.operations_suspended_ = false;
       this.is_formatted_tag_ = false;
+      this.data_transfer_failed_ = false;
     }
 
     // NFC delegate functions.
@@ -192,6 +193,9 @@
           // Resolves with NotAllowedError if there are NDEF records on the device
           // and overwrite is false.
           resolve(createNDEFError(device.mojom.NDEFErrorType.NOT_ALLOWED));
+        } else if (this.data_transfer_failed_) {
+          // Resolves with NetworkError if data transfer fails.
+          resolve(createNDEFError(device.mojom.NDEFErrorType.IO_ERROR));
         } else {
           resolve(createNDEFError(null));
         }
@@ -290,6 +294,7 @@
       this.operations_suspended_ = false;
       this.cancelPendingPushOperation();
       this.is_formatted_tag_ = false;
+      this.data_transfer_failed_ = false;
     }
 
     cancelPendingPushOperation() {
@@ -365,6 +370,10 @@
     setIsFormattedTag(isFormatted) {
       this.is_formatted_tag_ = isFormatted;
     }
+
+    simulateDataTransferFails() {
+      this.data_transfer_failed_ = true;
+    }
   }
 
   let testInternal = {
diff --git a/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
index ded320f0..b55c741 100644
--- a/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
@@ -6,11 +6,23 @@
 // https://w3c.github.io/server-timing/
 
 idl_test(
-  ['server-timing'],
-  ['resource-timing', 'performance-timeline'],
-  idl_array => {
-    idl_array.add_objects({
-      Performance: ['performance'],
-    });
-  }
+  ['resource-timing', 'server-timing'],
+  ['performance-timeline', 'hr-time', 'dom'],
+  idl_array => new Promise((resolve, reject) => {
+    new PerformanceObserver(entries => {
+      entries.getEntries().forEach(e => {
+        if (!e.name.endsWith('blue.png'))
+          return;
+
+        self.resource = e;
+        self.server = e.serverTiming[0];
+        idl_array.add_objects({
+          PerformanceResourceTiming: ['resource'],
+          PerformanceServerTiming: ['server']
+        });
+        resolve();
+      })
+    }).observe({entryTypes: ['resource']});
+    fetch('resources/blue.png');
+  })
 );
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt
deleted file mode 100644
index d1a5681..0000000
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS Registering within Service-Worker-Allowed path
-PASS Registering within Service-Worker-Allowed path (absolute URL)
-PASS Registering within Service-Worker-Allowed path with parent reference
-PASS Registering outside Service-Worker-Allowed path
-PASS Registering outside Service-Worker-Allowed path with parent reference
-FAIL Service-Worker-Allowed is cross-origin to script, registering on a normally allowed scope assert_unreached: Should have rejected: undefined Reached unreachable code
-FAIL Service-Worker-Allowed is cross-origin to script, registering on a normally disallowed scope assert_unreached: Should have rejected: undefined Reached unreachable code
-PASS Service-Worker-Allowed is cross-origin to page, same-origin to script
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-xhr.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-xhr.https-expected.txt
index 44c6a05..a354755 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-xhr.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-xhr.https-expected.txt
@@ -1,9 +1,9 @@
 This is a testharness.js-based test.
 PASS initialize global state
 FAIL event.request has the expected headers for same-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin GET. lengths differ, expected 1 got 3"
-FAIL event.request has the expected headers for same-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin POST. lengths differ, expected 2 got 5"
+FAIL event.request has the expected headers for same-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin POST. lengths differ, expected 2 got 4"
 FAIL event.request has the expected headers for cross-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin GET. lengths differ, expected 1 got 3"
-FAIL event.request has the expected headers for cross-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin POST. lengths differ, expected 2 got 5"
+FAIL event.request has the expected headers for cross-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin POST. lengths differ, expected 2 got 4"
 PASS FetchEvent#request.body contains XHR request data (string)
 PASS FetchEvent#request.body contains XHR request data (blob)
 PASS FetchEvent#request.method is set to XHR method
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py b/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
index 800d1f9..2131c70 100644
--- a/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
+++ b/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
@@ -339,6 +339,7 @@
                 self.filename == "META.yml" or
                 self.filename.startswith(".") or
                 self.filename.endswith(".headers") or
+                self.filename.endswith(".ini") or
                 self.in_non_test_dir())
 
     @property
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
index 33b5d51e..fee528071 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -8,7 +8,8 @@
                    cmd_arg,
                    browser_command)
 from ..executors.executormarionette import (MarionetteTestharnessExecutor,  # noqa: F401
-                                            MarionetteRefTestExecutor)  # noqa: F401
+                                            MarionetteRefTestExecutor,  # noqa: F401
+                                            MarionetteCrashtestExecutor)  # noqa: F401
 from .firefox import (get_timeout_multiplier,  # noqa: F401
                       run_info_extras as fx_run_info_extras,
                       update_properties,  # noqa: F401
@@ -20,7 +21,8 @@
                  "check_args": "check_args",
                  "browser": "FirefoxAndroidBrowser",
                  "executor": {"testharness": "MarionetteTestharnessExecutor",
-                              "reftest": "MarionetteRefTestExecutor"},
+                              "reftest": "MarionetteRefTestExecutor",
+                              "crashtest": "MarionetteCrashtestExecutor"},
                  "browser_kwargs": "browser_kwargs",
                  "executor_kwargs": "executor_kwargs",
                  "env_extras": "env_extras",
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 59f7e86..0130639 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
@@ -991,15 +991,16 @@
         if not success:
             status = data[0]
 
+        extra = None
         if self.debug and (success or status not in ("CRASH", "INTERNAL-ERROR")):
             assertion_count = self.protocol.asserts.get()
             if assertion_count is not None:
-                data["extra"] = {"assertion_count": assertion_count}
+                extra = {"assertion_count": assertion_count}
 
         if success:
             return self.convert_result(test, data)
 
-        return (test.result_cls(**data), [])
+        return (test.result_cls(extra=extra, *data), [])
 
     def do_crashtest(self, protocol, url, timeout):
         if self.protocol.coverage.is_enabled:
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 9b5f397..0b32921 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
@@ -535,7 +535,7 @@
         if success:
             return self.convert_result(test, data)
 
-        return (test.result_cls(**data), [])
+        return (test.result_cls(*data), [])
 
     def do_crashtest(self, protocol, url, timeout):
         protocol.base.load(url)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/test-wait.js b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
index 8a7edb79..ad08ad7 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
@@ -32,7 +32,8 @@
 }
 
 function screenshot_if_ready() {
-  if (root.classList.contains("%(classname)s") &&
+  if (root &&
+      root.classList.contains("%(classname)s") &&
       observer === null) {
     observer = new MutationObserver(wait_paints);
     observer.observe(root, {attributes: true});
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/font.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/font.py
index 6647a85..daf0a1c 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/font.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/font.py
@@ -1,5 +1,4 @@
 import ctypes
-import logging
 import os
 import platform
 import plistlib
@@ -12,7 +11,8 @@
 
 
 class FontInstaller(object):
-    def __init__(self, font_dir=None, **fonts):
+    def __init__(self, logger, font_dir=None, **fonts):
+        self.logger = logger
         self.font_dir = font_dir
         self.installed_fonts = False
         self.created_dir = False
@@ -26,14 +26,13 @@
             font_name = font_path.split('/')[-1]
             install = getattr(self, 'install_%s_font' % SYSTEM, None)
             if not install:
-                logging.warning('Font installation not supported on %s',
-                                SYSTEM)
+                self.logger.warning('Font installation not supported on %s' % SYSTEM)
                 return False
             if install(font_name, font_path):
                 self.installed_fonts = True
-                logging.info('Installed font: %s', font_name)
+                self.logger.info('Installed font: %s' % font_name)
             else:
-                logging.warning('Unable to install font: %s', font_name)
+                self.logger.warning('Unable to install font: %s' % font_name)
 
     def __exit__(self, exc_type, exc_val, exc_tb):
         if not self.installed_fonts:
@@ -43,12 +42,12 @@
             font_name = font_path.split('/')[-1]
             remove = getattr(self, 'remove_%s_font' % SYSTEM, None)
             if not remove:
-                logging.warning('Font removal not supported on %s', SYSTEM)
+                self.logger.warning('Font removal not supported on %s' % SYSTEM)
                 return False
             if remove(font_name, font_path):
-                logging.info('Removed font: %s', font_name)
+                self.logger.info('Removed font: %s' % font_name)
             else:
-                logging.warning('Unable to remove font: %s', font_name)
+                self.logger.warning('Unable to remove font: %s' % font_name)
 
     def install_linux_font(self, font_name, font_path):
         if not self.font_dir:
@@ -62,7 +61,7 @@
             fc_cache_returncode = call('fc-cache')
             return not fc_cache_returncode
         except OSError:  # If fontconfig doesn't exist, return False
-            logging.error('fontconfig not available on this Linux system.')
+            self.logger.error('fontconfig not available on this Linux system.')
             return False
 
     def install_darwin_font(self, font_name, font_path):
@@ -110,7 +109,7 @@
             fc_cache_returncode = call('fc-cache')
             return not fc_cache_returncode
         except OSError:  # If fontconfig doesn't exist, return False
-            logging.error('fontconfig not available on this Linux system.')
+            self.logger.error('fontconfig not available on this Linux system.')
             return False
 
     def remove_darwin_font(self, font_name, _):
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
index 7409dc2..75ce104 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -150,6 +150,7 @@
 
         if kwargs["install_fonts"]:
             env_extras.append(FontInstaller(
+                logger,
                 font_dir=kwargs["font_dir"],
                 ahem=os.path.join(test_paths["/"]["tests_path"], "fonts/Ahem.ttf")
             ))
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-expected.txt
index e86adfc..665b9fb 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 556 tests; 539 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 556 tests; 541 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setup
 PASS align-content (type: discrete) has testAddition function
 PASS align-content: "flex-end" onto "flex-start"
@@ -103,7 +103,7 @@
 PASS border-top-width: length
 PASS border-top-width: length of rem
 PASS box-shadow (type: boxShadowList) has testAddition function
-FAIL box-shadow: shadow assert_equals: The value should be rgb(0, 0, 0) 0px 0px 0px 0px, rgb(120, 120, 120) 10px 10px 10px 0px at 0ms expected "rgb(0, 0, 0) 0px 0px 0px 0px, rgb(120, 120, 120) 10px 10px 10px 0px" but got "rgb(120, 120, 120) 10px 10px 10px 0px"
+PASS box-shadow: shadow
 PASS box-sizing (type: discrete) has testAddition function
 PASS box-sizing: "border-box" onto "content-box"
 PASS box-sizing: "content-box" onto "border-box"
@@ -493,7 +493,7 @@
 PASS text-rendering: "optimizeLegibility" onto "optimizeSpeed"
 PASS text-rendering: "optimizeSpeed" onto "optimizeLegibility"
 PASS text-shadow (type: textShadowList) has testAddition function
-FAIL text-shadow: shadow assert_equals: The value should be rgb(0, 0, 0) 0px 0px 0px, rgb(120, 120, 120) 10px 10px 10px at 0ms expected "rgb(0, 0, 0) 0px 0px 0px, rgb(120, 120, 120) 10px 10px 10px" but got "rgb(120, 120, 120) 10px 10px 10px"
+PASS text-shadow: shadow
 PASS text-transform (type: discrete) has testAddition function
 PASS text-transform: "uppercase" onto "capitalize"
 PASS text-transform: "capitalize" onto "uppercase"
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/META.yml b/third_party/blink/web_tests/external/wpt/web-bundle/META.yml
new file mode 100644
index 0000000..0f1912b2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/META.yml
@@ -0,0 +1,5 @@
+spec: https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html
+suggested_reviewers:
+  - horo
+  - irori
+  - jyasskin
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/README.md b/third_party/blink/web_tests/external/wpt/web-bundle/README.md
new file mode 100644
index 0000000..03b42ab
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/README.md
@@ -0,0 +1,9 @@
+This directory contains tests for the
+[Web Bundles](https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html).
+
+`generate-test-wbns.sh` requires command-line tools in the
+[webpackage repository](https://github.com/WICG/webpackage).
+To install them, run:
+```
+go get -u github.com/WICG/webpackage/go/bundle/cmd/...
+```
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh b/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh
new file mode 100755
index 0000000..820bb12
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -e
+
+if ! command -v gen-bundle > /dev/null 2>&1; then
+    echo "gen-bundle is not installed. Please run:"
+    echo "  go get -u github.com/WICG/webpackage/go/bundle/cmd/..."
+    exit 1
+fi
+
+# TODO: Stop hard-coding "web-platform.test" when generating Web Bundles on the
+# fly.
+wpt_test_origin=https://web-platform.test:8444
+
+gen-bundle \
+  -version b1 \
+  -baseURL $wpt_test_origin/web-bundle/resources/wbn/ \
+  -primaryURL $wpt_test_origin/web-bundle/resources/wbn/location.html \
+  -dir location/ \
+  -o wbn/location.wbn
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.html b/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.html
new file mode 100644
index 0000000..e272dad2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<script src="./location.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.js b/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.js
new file mode 100644
index 0000000..a1dbba7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/location/location.js
@@ -0,0 +1,2 @@
+
+window.opener.postMessage({location: location.href}, '*');
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/__dir__.headers b/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/__dir__.headers
new file mode 100644
index 0000000..21e57b9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/__dir__.headers
@@ -0,0 +1,2 @@
+Content-Type: application/webbundle
+X-Content-Type-Options: nosniff
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/location.wbn b/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/location.wbn
new file mode 100644
index 0000000..1129cc1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/wbn/location.wbn
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/wbn-location.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/wbn-location.tentative.html
new file mode 100644
index 0000000..e0604af
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/wbn-location.tentative.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Location of a page in a Web Bundle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+  const location_promise = new Promise((resolve, reject) => {
+    let win = null;
+    window.addEventListener(
+        'message',
+        (event) => {
+          win.close();
+          resolve(event.data.location);
+        }, false);
+    win = window.open(
+        get_host_info().HTTPS_ORIGIN + '/web-bundle/resources/wbn/location.wbn',
+        '_blank');
+    if (!win) {
+      reject('Popup could not be opened');
+    }
+  });
+  assert_equals(
+      await location_promise,
+      get_host_info().HTTPS_ORIGIN + '/web-bundle/resources/wbn/location.html');
+}, 'Location of a page in a Web Bundle');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReader_scan.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReader_scan.https.html
index a9b1d75..17b9fdb8 100644
--- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReader_scan.https.html
+++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReader_scan.https.html
@@ -207,4 +207,27 @@
 }, "Test that NDEFReader.onreading should be fired on an unformatted NFC tag \
 with empty records array for NDEFMessage.");
 
+nfc_test(async (t, mockNFC) => {
+  const reader = new NDEFReader();
+  const controller = new AbortController();
+  const message = createMessage([createTextRecord(test_text_data),
+                                createMimeRecordFromJson(test_json_data),
+                                createMimeRecord(test_buffer_data),
+                                createUnknownRecord(test_buffer_data),
+                                createUrlRecord(test_url_data),
+                                createUrlRecord(test_url_data, true),
+                                createRecord('w3.org:xyz', test_buffer_data)],
+                                test_message_origin);
+  const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+  const promise = readerWatcher.wait_for("reading").then(event => {
+    assert_equals(event.serialNumber, fake_tag_serial_number);
+    assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message));
+    controller.abort();
+  });
+  await reader.scan({signal : controller.signal});
+
+  mockNFC.setReadingMessage(message);
+  await promise;
+}, "Test that reading message with multiple records should succeed.");
+
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https-expected.txt b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https-expected.txt
index 08edb6f..7c6b03b0 100644
--- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https-expected.txt
@@ -28,5 +28,6 @@
 PASS NDEFWriter.push should succeed to push data to an unformatted NFC device when the NDEFPushOptions.overwrite is false.
 PASS NDEFWriter.push should succeed to overwrite the existing data when the NDEFPushOptions.overwrite is true.
 FAIL NDEFWriter.push should fail when there are NDEF records on the NFC device and NDEFPushOptions.overwrite is false. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS NDEFWriter.push should fail with NetworkError when NFC data transfer fails.
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https.html
index 4ff0af8f..cb6b3941 100644
--- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https.html
+++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_push.https.html
@@ -276,7 +276,7 @@
 
 nfc_test(async (t, mockNFC) => {
   const writer = new NDEFWriter();
-  let message = createMessage([createTextRecord(test_text_data),
+  const message = createMessage([createTextRecord(test_text_data),
                                createMimeRecordFromJson(test_json_data),
                                createMimeRecord(test_buffer_data),
                                createUnknownRecord(test_buffer_data),
@@ -308,9 +308,12 @@
   assertNDEFMessagesEqual(buffer_view, mockNFC.pushedMessage());
 }, "Test that NDEFWriter.push succeeds when message is ArrayBufferView.");
 
-nfc_test(async () => {
+nfc_test(async (t, mockNFC) => {
   const writer = new NDEFWriter();
   await writer.push(createMessage([createRecord('empty')]));
+  const receivedMessage = mockNFC.pushedMessage();
+  assert_equals(receivedMessage.data.length, 1);
+  assert_equals(receivedMessage.data[0].recordType, 'empty', 'recordType');
 }, "NDEFWriter.push with 'empty' record should succeed.");
 
 nfc_test(async (t, mockNFC) => {
@@ -433,4 +436,11 @@
   await promise_rejects(t, 'NotAllowedError', p);
 }, "NDEFWriter.push should fail when there are NDEF records on the NFC device \
 and NDEFPushOptions.overwrite is false.");
+
+nfc_test(async (t, mockNFC) => {
+  const writer = new NDEFWriter();
+  mockNFC.simulateDataTransferFails();
+  await promise_rejects(t, 'NetworkError', writer.push(test_text_data));
+}, "NDEFWriter.push should fail with NetworkError when NFC data transfer fails.");
+
 </script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
index c85e853..0e5ceb9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
@@ -29,6 +29,7 @@
  Background Sync
  Notifications
  Payment Handler
+ Periodic Background Sync
  Push Messaging
 Frames
  top
@@ -58,6 +59,7 @@
  Background Sync
  Notifications
  Payment Handler
+ Periodic Background Sync
  Push Messaging
 Frames
  top
@@ -91,6 +93,7 @@
  Background Sync
  Notifications
  Payment Handler
+ Periodic Background Sync
  Push Messaging
 Frames
  top
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
index b237b5f..e751a88 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
@@ -24,6 +24,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -52,6 +53,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
index e340077..9b7f6ee 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
@@ -22,6 +22,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -48,6 +49,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -79,6 +81,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -110,6 +113,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
index fafe35c..8b922f4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
@@ -24,6 +24,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -53,6 +54,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
index b87f320..1cdfce40 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
@@ -22,6 +22,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -49,6 +50,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
@@ -76,6 +78,7 @@
   Background Sync
   Notifications
   Payment Handler
+  Periodic Background Sync
   Push Messaging
 Frames
   top
diff --git a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
index 838d5e2..0d4b00e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
@@ -16,6 +16,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 ============================
 The second Serviceworker is installed.
 ==== ServiceWorkersView ====
@@ -38,6 +40,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 ============================
 The first ServiceWorker worker became redundant and stopped.
 ==== ServiceWorkersView ====
@@ -55,5 +59,7 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 ============================
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
index b2e4e1f1..c343f72e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
@@ -16,6 +16,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 Register ServiceWorker for scope2
 http://127.0.0.1:8000/devtools/service-workers/resources/scope2
 Update
@@ -31,6 +33,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 http://127.0.0.1:8000/devtools/service-workers/resources/scope1/
 Update
 Unregister
@@ -45,6 +49,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 Unregister ServiceWorker for scope1
 http://127.0.0.1:8000/devtools/service-workers/resources/scope2
 Update
@@ -60,6 +66,8 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 http://127.0.0.1:8000/devtools/service-workers/resources/scope1/ - deleted
 Update
 Unregister
@@ -73,5 +81,7 @@
 Push
 Sync
 Sync
+Periodic Sync
+Periodic Sync
 Unregister ServiceWorker for scope2
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob-expected.txt
new file mode 100644
index 0000000..7ad3af3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob-expected.txt
@@ -0,0 +1,3 @@
+Verifies that we can retrieve a request body consisting of blob in service worker.
+post data: Psychrolutes microporos
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob.js b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob.js
new file mode 100644
index 0000000..0aa327fb
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/network-get-request-body-blob.js
@@ -0,0 +1,31 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startBlank(
+      'Verifies that we can retrieve a request body consisting of blob in service worker.');
+  const swHelper = (await testRunner.loadScript('resources/service-worker-helper.js'))(dp, session);
+
+  let swdp = null;
+  await dp.Target.setAutoAttach(
+    {autoAttach: true, waitForDebuggerOnStart: false, flatten: true});
+  dp.Target.onAttachedToTarget(async event => {
+    swdp = session.createChild(event.params.sessionId).protocol;
+  });
+
+  const serviceWorkerURL = '/inspector-protocol/service-worker/resources/blank-service-worker.js';
+  await session.navigate('resources/repeat-fetch-service-worker.html');
+  await swHelper.installSWAndWaitForActivated(serviceWorkerURL);
+
+  await dp.Page.enable();
+  await dp.Page.reload();
+  await swHelper.installSWAndWaitForActivated(serviceWorkerURL);
+  await swdp.Network.enable();
+  await swdp.Runtime.enable();
+  const postBlobFromServiceWorker = `
+      fetch('/', { method: "POST", body: new Blob(['Psychrolutes ', 'microporos']) });
+  `;
+  swdp.Runtime.evaluate({expression: postBlobFromServiceWorker});
+  const requestId = (await swdp.Network.onceRequestWillBeSent()).params.requestId;
+  const body = (await swdp.Network.getRequestPostData({requestId})).result.postData;
+  testRunner.log(`post data: ${body}`);
+
+  testRunner.completeTest();
+});
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/resources/blank-service-worker.js b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/resources/blank-service-worker.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/resources/blank-service-worker.js
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-19b-expected.png
index 64a4860e..ffa1b33a 100644
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-19b-expected.png
index 64a4860e..ffa1b33a 100644
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-19b-expected.png
index 4219d47..d2ff537 100644
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/pasteboard/input-field-1-expected.txt b/third_party/blink/web_tests/platform/linux/editing/pasteboard/input-field-1-expected.txt
index ccc0a915..d5438af 100644
--- a/third_party/blink/web_tests/platform/linux/editing/pasteboard/input-field-1-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/editing/pasteboard/input-field-1-expected.txt
@@ -12,8 +12,8 @@
         LayoutText {#text} at (0,0) size 235x19
           text run at (0,0) width 235: "This tests Copy/Paste of a input field."
       LayoutBlockFlow {DIV} at (0,36) size 784x22
-        LayoutTextControl {INPUT} at (0,0) size 181x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutTextControl {INPUT} at (181,0) size 181x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
+        LayoutTextControl {INPUT} at (0,0) size 181x22 [bgcolor=#FFFFFF] [border: (2px inset #767676)]
+        LayoutTextControl {INPUT} at (181,0) size 181x22 [bgcolor=#FFFFFF] [border: (2px inset #767676)]
       LayoutBlockFlow {UL} at (0,74) size 784x20
         LayoutListItem {LI} at (40,0) size 744x20
           LayoutListMarker (anonymous) at (-18,0) size 7x19: bullet
diff --git a/third_party/blink/web_tests/platform/linux/editing/pasteboard/pasting-tabs-expected.txt b/third_party/blink/web_tests/platform/linux/editing/pasteboard/pasting-tabs-expected.txt
index 794ac09..d9fcb77 100644
--- a/third_party/blink/web_tests/platform/linux/editing/pasteboard/pasting-tabs-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/editing/pasteboard/pasting-tabs-expected.txt
@@ -24,7 +24,7 @@
         LayoutText {#text} at (64,0) size 38x19
           text run at (64,0) width 38: "<-Tab"
 layer at (8,64) size 179x36 clip at (9,65) size 177x34
-  LayoutTextControl {TEXTAREA} at (0,0) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+  LayoutTextControl {TEXTAREA} at (0,0) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
     LayoutBlockFlow {DIV} at (3,3) size 175x16
       LayoutText {#text} at (0,0) size 104x16
         text run at (0,0) width 104: "Tab->\x{9}<-Tab"
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/replaced-boundaries-3-expected.txt b/third_party/blink/web_tests/platform/linux/editing/selection/replaced-boundaries-3-expected.txt
index 77228e0..62ce168 100644
--- a/third_party/blink/web_tests/platform/linux/editing/selection/replaced-boundaries-3-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/editing/selection/replaced-boundaries-3-expected.txt
@@ -15,7 +15,7 @@
         LayoutText {#text} at (0,0) size 22x19
           text run at (0,0) width 22: "abc"
         LayoutBR {BR} at (22,15) size 0x0
-        LayoutMenuList {SELECT} at (0,20) size 233x20 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+        LayoutMenuList {SELECT} at (0,20) size 233x20 [bgcolor=#DDDDDD] [border: (1px solid #767676)]
           LayoutBlockFlow (anonymous) at (1,1) size 231x18
             LayoutText (anonymous) at (4,1) size 211x16
               text run at (4,1) width 211: "this select box shouldn't be selected"
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/select-box-expected.txt b/third_party/blink/web_tests/platform/linux/editing/selection/select-box-expected.txt
index 06f42ec..c3e5c33 100644
--- a/third_party/blink/web_tests/platform/linux/editing/selection/select-box-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/editing/selection/select-box-expected.txt
@@ -62,7 +62,7 @@
         LayoutBlockFlow {DIV} at (0,0) size 784x20
           LayoutText {#text} at (0,0) size 71x19
             text run at (0,0) width 71: "select box: "
-          LayoutMenuList {SELECT} at (71,0) size 29x20 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutMenuList {SELECT} at (71,0) size 29x20 [bgcolor=#DDDDDD] [border: (1px solid #767676)]
             LayoutBlockFlow (anonymous) at (1,1) size 27x18
               LayoutText (anonymous) at (4,1) size 7x16
                 text run at (4,1) width 7: "1"
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/select-element-paragraph-boundary-expected.txt b/third_party/blink/web_tests/platform/linux/editing/selection/select-element-paragraph-boundary-expected.txt
index a369867..0f0d62e 100644
--- a/third_party/blink/web_tests/platform/linux/editing/selection/select-element-paragraph-boundary-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/editing/selection/select-element-paragraph-boundary-expected.txt
@@ -11,7 +11,7 @@
           text run at (326,0) width 423: "The caret should be at the end of the paragraph below, just after the"
           text run at (0,20) width 67: "select box."
       LayoutBlockFlow {DIV} at (0,56) size 784x20
-        LayoutMenuList {SELECT} at (0,0) size 29x20 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+        LayoutMenuList {SELECT} at (0,0) size 29x20 [bgcolor=#DDDDDD] [border: (1px solid #767676)]
           LayoutBlockFlow (anonymous) at (1,1) size 27x18
             LayoutText (anonymous) at (4,1) size 7x16
               text run at (4,1) width 7: "1"
diff --git a/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
index 007cf99..71a6c5d 100644
--- a/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/block/margin-collapse/103-expected.png b/third_party/blink/web_tests/platform/linux/fast/block/margin-collapse/103-expected.png
index 70fefa4..355b73b 100644
--- a/third_party/blink/web_tests/platform/linux/fast/block/margin-collapse/103-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/block/margin-collapse/103-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/continuationCrash-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/continuationCrash-expected.png
index f34fda2..62e2a9c 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css/continuationCrash-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css/continuationCrash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/margin-top-bottom-dynamic-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/margin-top-bottom-dynamic-expected.png
index 37ef0ecf..d5fee006 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css/margin-top-bottom-dynamic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css/margin-top-bottom-dynamic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/text-overflow-input-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/text-overflow-input-expected.png
index 3ac0358..1010917 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css/text-overflow-input-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
index ad09ec2b..c7e1206 100644
--- a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-optimums-expected.png
index 0748f00..03456901 100644
--- a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-optimums-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-optimums-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-styles-expected.png
index 2e75e3c..da233b83 100644
--- a/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-styles-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/dom/HTMLMeterElement/meter-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/parser/document-write-option-expected.png b/third_party/blink/web_tests/platform/linux/fast/parser/document-write-option-expected.png
index 8e446e7..3585e51 100644
--- a/third_party/blink/web_tests/platform/linux/fast/parser/document-write-option-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/parser/document-write-option-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/replaced/replaced-breaking-expected.png b/third_party/blink/web_tests/platform/linux/fast/replaced/replaced-breaking-expected.png
index 85f42c6..761aec4 100644
--- a/third_party/blink/web_tests/platform/linux/fast/replaced/replaced-breaking-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/replaced/replaced-breaking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/replaced/width100percent-button-expected.png b/third_party/blink/web_tests/platform/linux/fast/replaced/width100percent-button-expected.png
index a89f4a7..e6ed8b92 100644
--- a/third_party/blink/web_tests/platform/linux/fast/replaced/width100percent-button-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/replaced/width100percent-button-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
index 65bfa7b..d25098f 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png
new file mode 100644
index 0000000..b39e495
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/custom/foreign-object-skew-expected.png b/third_party/blink/web_tests/platform/linux/svg/custom/foreign-object-skew-expected.png
index d8f53da..8e5555a 100644
--- a/third_party/blink/web_tests/platform/linux/svg/custom/foreign-object-skew-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/custom/foreign-object-skew-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug18359-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug18359-expected.png
index a57e5a1..1a0e975 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug18359-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug18359-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug194024-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug194024-expected.png
index f8e9703c..23abe87 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug194024-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug194024-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
index 659b30d2c..60efae4c 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug2479-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug33855-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug33855-expected.png
index 1526af7f..c9b51d8d9 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug33855-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug33855-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug4382-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug4382-expected.png
index 5f236dea..19472a76 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug4382-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug4382-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug44505-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug44505-expected.png
index c75fa4b..65c9b92f 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug44505-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug44505-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug51727-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug51727-expected.png
index 5103266..a2d8997 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug51727-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug51727-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52505-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52505-expected.png
index 680fb2ea..717bbb8 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52505-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52505-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52506-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52506-expected.png
index 9f0daac..f78f23ed 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52506-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug52506-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug60749-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug60749-expected.png
index de62a86b..e057c4f 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug60749-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla/bugs/bug60749-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
index c7fe059..282ab57b 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png b/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
index bd49ccc7..4bf4c212 100644
--- a/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
+++ b/third_party/blink/web_tests/platform/linux/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/transforms/2d/zoom-menulist-expected.png b/third_party/blink/web_tests/platform/linux/transforms/2d/zoom-menulist-expected.png
index 69e87ff..7550d47 100644
--- a/third_party/blink/web_tests/platform/linux/transforms/2d/zoom-menulist-expected.png
+++ b/third_party/blink/web_tests/platform/linux/transforms/2d/zoom-menulist-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/button-style-color-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/button-style-color-expected.png
new file mode 100644
index 0000000..462c844
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/button-style-color-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
new file mode 100644
index 0000000..3ca13b5702
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png
new file mode 100644
index 0000000..0502a01b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..5855a36
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..64fe9ab
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..a4304e8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/select/basic-selects-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/select/basic-selects-expected.png
new file mode 100644
index 0000000..8d192ef4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/select/basic-selects-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png
new file mode 100644
index 0000000..347d511
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png
new file mode 100644
index 0000000..57589ae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png
new file mode 100644
index 0000000..e126e63
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
index 86dbef8..5f058af 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
new file mode 100644
index 0000000..c7e1206
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
new file mode 100644
index 0000000..f840958
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
@@ -0,0 +1,10 @@
+PASS cloned.value is target.value
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild.firstChild)
+PASS clonedShadowRoot.firstChild.firstChild.firstChild.style.width is "70%"
+PASS targetShadowRoot.firstChild.firstChild.firstChild.style.width is "50%"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
new file mode 100644
index 0000000..a39a6a3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
@@ -0,0 +1,75 @@
+
+Both meter elements should have a nested shadow box with a width specified:
+| "
+    "
+| <meter>
+|   max="100"
+|   value="70"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-optimum-value"
+|           style="width: 70%;"
+|           shadow:pseudoId="-webkit-meter-optimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="5"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-suboptimum-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-suboptimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="0"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-even-less-good-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-even-less-good-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+  "
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
new file mode 100644
index 0000000..03456901
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
new file mode 100644
index 0000000..da233b83
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/parser/document-write-option-expected.png b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/parser/document-write-option-expected.png
new file mode 100644
index 0000000..3585e51
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/web-components-v0-disabled/fast/parser/document-write-option-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..91bb6c6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/trailing-white-space-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/trailing-white-space-2-expected.png
index 08e8e87..9083dbf 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/trailing-white-space-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/trailing-white-space-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..91bb6c6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..91bb6c6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..91bb6c6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
index b013bb5..91bb6c6 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
index 321b7ab..b58d39c 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/trailing-white-space-2-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/trailing-white-space-2-expected.png
index af184558..b5af8ad6 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/trailing-white-space-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/trailing-white-space-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/control-layer-expected.txt b/third_party/blink/web_tests/platform/win/compositing/contents-opaque/control-layer-expected.txt
similarity index 92%
rename from third_party/blink/web_tests/compositing/contents-opaque/control-layer-expected.txt
rename to third_party/blink/web_tests/platform/win/compositing/contents-opaque/control-layer-expected.txt
index 603dee66..f287949 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/control-layer-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/contents-opaque/control-layer-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutButton INPUT id='control' class='composited'",
       "bounds": [127, 22],
-      "backgroundColor": "#DDDDDD",
+      "backgroundColor": "#EFEFEF",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-19b-expected.png
index 4d8e3fb..d84df6e 100644
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-19b-expected.png
index 4d8e3fb..d84df6e 100644
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-19b-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-19b-expected.png
index a26fb115..85f1a85 100644
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-19b-expected.png
+++ b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-19b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.png b/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.png
index 0fad8beb..a5e3c30f 100644
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.txt b/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.txt
index 162f048..893b9c5 100644
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.txt
+++ b/third_party/blink/web_tests/platform/win/editing/pasteboard/input-field-1-expected.txt
@@ -12,8 +12,8 @@
         LayoutText {#text} at (0,0) size 224x19
           text run at (0,0) width 224: "This tests Copy/Paste of a input field."
       LayoutBlockFlow {DIV} at (0,36) size 784x22
-        LayoutTextControl {INPUT} at (0,0) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutTextControl {INPUT} at (173,0) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
+        LayoutTextControl {INPUT} at (0,0) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #767676)]
+        LayoutTextControl {INPUT} at (173,0) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #767676)]
       LayoutBlockFlow {UL} at (0,74) size 784x20
         LayoutListItem {LI} at (40,0) size 744x20
           LayoutListMarker (anonymous) at (-18,0) size 7x19: bullet
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.png b/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.png
index 7aff11b..932ba6b 100644
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.txt b/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.txt
index 84a6ef8..0608040 100644
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.txt
+++ b/third_party/blink/web_tests/platform/win/editing/pasteboard/pasting-tabs-expected.txt
@@ -24,7 +24,7 @@
         LayoutText {#text} at (64,0) size 38x19
           text run at (64,0) width 38: "<-Tab"
 layer at (8,64) size 179x36 clip at (9,65) size 177x34
-  LayoutTextControl {TEXTAREA} at (0,0) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+  LayoutTextControl {TEXTAREA} at (0,0) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
     LayoutBlockFlow {DIV} at (3,3) size 175x16
       LayoutText {#text} at (0,0) size 104x16
         text run at (0,0) width 104: "Tab->\x{9}<-Tab"
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.png
index 9ab3ecf..ebefac1 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.txt b/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.txt
index 568d8f9b..31fa424 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.txt
+++ b/third_party/blink/web_tests/platform/win/editing/selection/replaced-boundaries-3-expected.txt
@@ -16,7 +16,7 @@
         LayoutText {#text} at (0,0) size 22x19
           text run at (0,0) width 22: "abc"
         LayoutBR {BR} at (22,15) size 0x0
-        LayoutMenuList {SELECT} at (0,20) size 235x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutMenuList {SELECT} at (0,20) size 235x20 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
           LayoutBlockFlow (anonymous) at (1,1) size 233x18
             LayoutText (anonymous) at (4,1) size 211x16
               text run at (4,1) width 211: "this select box shouldn't be selected"
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.png
index 6cac889..2edf8cfb 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.txt b/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.txt
index 3383fd2..f9903cf3 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.txt
+++ b/third_party/blink/web_tests/platform/win/editing/selection/select-box-expected.txt
@@ -62,7 +62,7 @@
         LayoutBlockFlow {DIV} at (0,0) size 784x20
           LayoutText {#text} at (0,0) size 68x19
             text run at (0,0) width 68: "select box: "
-          LayoutMenuList {SELECT} at (68,0) size 31x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+          LayoutMenuList {SELECT} at (68,0) size 31x20 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
             LayoutBlockFlow (anonymous) at (1,1) size 29x18
               LayoutText (anonymous) at (4,1) size 7x16
                 text run at (4,1) width 7: "1"
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.png
index 8ccf267..c831b82 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.txt b/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.txt
index dc09273..b77b9295 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.txt
+++ b/third_party/blink/web_tests/platform/win/editing/selection/select-element-paragraph-boundary-expected.txt
@@ -10,7 +10,7 @@
           text run at (0,0) width 308: "This tests paragraphBoundary selection navigation. "
           text run at (308,0) width 476: "The caret should be at the end of the paragraph below, just after the select box."
       LayoutBlockFlow {DIV} at (0,36) size 784x20
-        LayoutMenuList {SELECT} at (0,0) size 31x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutMenuList {SELECT} at (0,0) size 31x20 [bgcolor=#FFFFFF] [border: (1px solid #767676)]
           LayoutBlockFlow (anonymous) at (1,1) size 29x18
             LayoutText (anonymous) at (4,1) size 7x16
               text run at (4,1) width 7: "1"
diff --git a/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
index cc01841..e23fea3 100644
--- a/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/block/margin-collapse/103-expected.png b/third_party/blink/web_tests/platform/win/fast/block/margin-collapse/103-expected.png
index 1b33dc75..45fdb96b 100644
--- a/third_party/blink/web_tests/platform/win/fast/block/margin-collapse/103-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/block/margin-collapse/103-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/continuationCrash-expected.png b/third_party/blink/web_tests/platform/win/fast/css/continuationCrash-expected.png
index af3fb97..fc217a1 100644
--- a/third_party/blink/web_tests/platform/win/fast/css/continuationCrash-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css/continuationCrash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/margin-top-bottom-dynamic-expected.png b/third_party/blink/web_tests/platform/win/fast/css/margin-top-bottom-dynamic-expected.png
index eedcd33..04aec85 100644
--- a/third_party/blink/web_tests/platform/win/fast/css/margin-top-bottom-dynamic-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css/margin-top-bottom-dynamic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/text-overflow-input-expected.png b/third_party/blink/web_tests/platform/win/fast/css/text-overflow-input-expected.png
index cabe0e7..d6b80cf 100644
--- a/third_party/blink/web_tests/platform/win/fast/css/text-overflow-input-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
index ff230cd..26801a1 100644
--- a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-optimums-expected.png
index 1f8becc..3e49328 100644
--- a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-optimums-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-optimums-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-styles-expected.png
index 40886fe..c7507d3 100644
--- a/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-styles-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/dom/HTMLMeterElement/meter-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/parser/document-write-option-expected.png b/third_party/blink/web_tests/platform/win/fast/parser/document-write-option-expected.png
index f4045f4..4d40181a 100644
--- a/third_party/blink/web_tests/platform/win/fast/parser/document-write-option-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/parser/document-write-option-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/replaced/replaced-breaking-expected.png b/third_party/blink/web_tests/platform/win/fast/replaced/replaced-breaking-expected.png
index a12437b..8ea9391 100644
--- a/third_party/blink/web_tests/platform/win/fast/replaced/replaced-breaking-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/replaced/replaced-breaking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/replaced/width100percent-button-expected.png b/third_party/blink/web_tests/platform/win/fast/replaced/width100percent-button-expected.png
index 41cda98b..b4926a3 100644
--- a/third_party/blink/web_tests/platform/win/fast/replaced/width100percent-button-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/replaced/width100percent-button-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
index 16af582..4090a5bb 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/button-checkbox-click-method-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png
index b39e495..37050d9 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.txt
index 18516f7..8216fbe 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/range-focus-by-mouse-then-keydown-expected.txt
@@ -8,12 +8,12 @@
       "paintInvalidations": [
         {
           "object": "LayoutSlider INPUT",
-          "rect": [9, 9, 131, 23],
+          "rect": [9, 9, 131, 18],
           "reason": "subtree"
         },
         {
           "object": "LayoutBlockFlow DIV id='thumb'",
-          "rect": [69, 10, 11, 21],
+          "rect": [66, 10, 17, 16],
           "reason": "subtree"
         }
       ]
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/select-option-background-color-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/select-option-background-color-expected.txt
index b3c16e0..d1ab9481 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/forms/select-option-background-color-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/forms/select-option-background-color-expected.txt
@@ -7,9 +7,19 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow OPTION id='option'",
+          "object": "VerticalScrollbar",
+          "rect": [14, 37, 15, 68],
+          "reason": "disappeared"
+        },
+        {
+          "object": "VerticalScrollbar",
+          "rect": [14, 37, 15, 68],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutListBox SELECT",
           "rect": [1, 37, 13, 17],
-          "reason": "appeared"
+          "reason": "chunk appeared"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/platform/win/svg/custom/foreign-object-skew-expected.png b/third_party/blink/web_tests/platform/win/svg/custom/foreign-object-skew-expected.png
index 6b395d5..3c38f0793 100644
--- a/third_party/blink/web_tests/platform/win/svg/custom/foreign-object-skew-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/custom/foreign-object-skew-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug18359-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug18359-expected.png
index 0d5a9dc..707a8ff 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug18359-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug18359-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug194024-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug194024-expected.png
index 19da395..72706cb 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug194024-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug194024-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug2479-3-expected.png
index d1effd488..21b7f8a 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug2479-3-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug2479-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug33855-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug33855-expected.png
index 4116e5c..d30f412 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug33855-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug33855-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug4382-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug4382-expected.png
index 1283eec..d51caf9 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug4382-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug4382-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug44505-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug44505-expected.png
index edef875..7d33580 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug44505-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug44505-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug51727-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug51727-expected.png
index 714b8bb8..091099e 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug51727-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug51727-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52505-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52505-expected.png
index e4fbe50..0be8ed6 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52505-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52505-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52506-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52506-expected.png
index 0312d91..7a593134 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52506-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug52506-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug60749-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug60749-expected.png
index 67476bcb3..fb579e6a 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug60749-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla/bugs/bug60749-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
index c3121c60..9ed96ae 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-5-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png b/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
index 5235bfd..efda63c 100644
--- a/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
+++ b/third_party/blink/web_tests/platform/win/tables/mozilla_expected_failures/collapsing_borders/bug41262-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/transforms/2d/zoom-menulist-expected.png b/third_party/blink/web_tests/platform/win/transforms/2d/zoom-menulist-expected.png
index 05f774f..0c21318 100644
--- a/third_party/blink/web_tests/platform/win/transforms/2d/zoom-menulist-expected.png
+++ b/third_party/blink/web_tests/platform/win/transforms/2d/zoom-menulist-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/button-style-color-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/button-style-color-expected.png
new file mode 100644
index 0000000..bea8447
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/button-style-color-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
new file mode 100644
index 0000000..4fa11a7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png
new file mode 100644
index 0000000..93536ba2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/color/color-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..a9fe52b3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..4f3f951
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..0e1c41f4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/select/basic-selects-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/select/basic-selects-expected.png
new file mode 100644
index 0000000..7022d4f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/select/basic-selects-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png
new file mode 100644
index 0000000..35a66bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/submit/submit-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png
new file mode 100644
index 0000000..7ea41360
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/text/text-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png
new file mode 100644
index 0000000..cefac39
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cascade/fast/forms/textarea/textarea-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..0138770
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
index 35e9401..d83805f 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
index aa414caa..f6de4f4d 100644
--- a/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
new file mode 100644
index 0000000..26801a1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
new file mode 100644
index 0000000..f840958
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
@@ -0,0 +1,10 @@
+PASS cloned.value is target.value
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild.firstChild)
+PASS clonedShadowRoot.firstChild.firstChild.firstChild.style.width is "70%"
+PASS targetShadowRoot.firstChild.firstChild.firstChild.style.width is "50%"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
new file mode 100644
index 0000000..a39a6a3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
@@ -0,0 +1,75 @@
+
+Both meter elements should have a nested shadow box with a width specified:
+| "
+    "
+| <meter>
+|   max="100"
+|   value="70"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-optimum-value"
+|           style="width: 70%;"
+|           shadow:pseudoId="-webkit-meter-optimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="5"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-suboptimum-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-suboptimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="0"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-even-less-good-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-even-less-good-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+  "
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
new file mode 100644
index 0000000..3e49328
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
new file mode 100644
index 0000000..c7507d3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
new file mode 100644
index 0000000..87cfe7c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..4e5957c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..b835a870b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cascade/fast/forms/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
new file mode 100644
index 0000000..0138770
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh-hc/virtual/controls-refresh/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
index 634228d8..a3d8c91 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
new file mode 100644
index 0000000..26801a1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-boundary-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
new file mode 100644
index 0000000..f840958
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-clone-expected.txt
@@ -0,0 +1,10 @@
+PASS cloned.value is target.value
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild)
+PASS internals.shadowPseudoId(clonedShadowRoot.firstChild.firstChild.firstChild) is internals.shadowPseudoId(targetShadowRoot.firstChild.firstChild.firstChild)
+PASS clonedShadowRoot.firstChild.firstChild.firstChild.style.width is "70%"
+PASS targetShadowRoot.firstChild.firstChild.firstChild.style.width is "50%"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
new file mode 100644
index 0000000..a39a6a3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-element-markup-expected.txt
@@ -0,0 +1,75 @@
+
+Both meter elements should have a nested shadow box with a width specified:
+| "
+    "
+| <meter>
+|   max="100"
+|   value="70"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-optimum-value"
+|           style="width: 70%;"
+|           shadow:pseudoId="-webkit-meter-optimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="5"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-suboptimum-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-suboptimum-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+    "
+| <meter>
+|   high="6"
+|   low="3"
+|   max="10"
+|   min="0"
+|   optimum="0"
+|   value="10"
+|   <shadow:root>
+|     <div>
+|       pseudo="-webkit-meter-inner-element"
+|       shadow:pseudoId="-webkit-meter-inner-element"
+|       <div>
+|         pseudo="-webkit-meter-bar"
+|         shadow:pseudoId="-webkit-meter-bar"
+|         <div>
+|           pseudo="-webkit-meter-even-less-good-value"
+|           style="width: 100%;"
+|           shadow:pseudoId="-webkit-meter-even-less-good-value"
+|     <div>
+|       pseudo="-internal-fallback"
+|       shadow:pseudoId="-internal-fallback"
+|       <slot>
+|         name="user-agent-default-slot"
+| "
+  "
diff --git a/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
new file mode 100644
index 0000000..3e49328
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-optimums-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
new file mode 100644
index 0000000..c7507d3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/web-components-v0-disabled/fast/dom/HTMLMeterElement/meter-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/wbn-from-network/README.md b/third_party/blink/web_tests/virtual/wbn-from-network/README.md
new file mode 100644
index 0000000..1bee455
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/wbn-from-network/README.md
@@ -0,0 +1 @@
+This directory is for testing the WebBundlesFromNetwork feature.
diff --git a/third_party/blink/web_tests/virtual/wbn-from-network/external/wpt/web-bundle/README.txt b/third_party/blink/web_tests/virtual/wbn-from-network/external/wpt/web-bundle/README.txt
new file mode 100644
index 0000000..1bee455
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/wbn-from-network/external/wpt/web-bundle/README.txt
@@ -0,0 +1 @@
+This directory is for testing the WebBundlesFromNetwork feature.
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 38f1ae7..a3e3b4c 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-10-1-93-g10d8de754
-Revision: 10d8de7541ab1f26f6f04b2118d13a92a7119102
+Version: VER-2-10-1-95-g50b013871
+Revision: 50b013871c53f7624b5351dd4820a137303fe14b
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
 License File: src/docs/FTL.TXT
diff --git a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc
index e5afcee..0e97bd1 100644
--- a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc
+++ b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc
@@ -4,48 +4,70 @@
 
 #include "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h"
 
-#include "base/debug/stack_trace.h"
-#include "base/format_macros.h"
-
-namespace {
-
-// The number of frames on the top of the stack to ignore in UponLeavingGTest.
-// This may vary from build to build and platform to platform. On Windows
-// release builds at the time of writing, the top two frames should be skipped:
-//   base::debug::StackTrace::StackTrace
-//   StackTraceGetter::UponLeavingGTest
-enum : size_t { kDepartureSkipFrames = 2 };
-
-}  // namespace
+#include <algorithm>
+#include <iterator>
 
 std::string StackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) {
   base::debug::StackTrace stack_trace;
 
-  size_t frame_count = 0;
-  const void* const* addresses = stack_trace.Addresses(&frame_count);
+  size_t departure_frame_count = 0;
+  const void* const* departure_addresses =
+      stack_trace_upon_leaving_gtest_->Addresses(&departure_frame_count);
 
-  // Drop the frames at the tail that were present the last time gtest was left.
-  if (frame_count_upon_leaving_gtest_ &&
-      frame_count > frame_count_upon_leaving_gtest_) {
-    frame_count -= frame_count_upon_leaving_gtest_;
+  size_t current_frame_count = 0;
+  const void* const* current_addresses =
+      stack_trace.Addresses(&current_frame_count);
+
+  // Ignore the frames at the root of the current trace that match those of the
+  // point of departure from GTest. These frames all relate to thread start and
+  // test setup, and are irrelevant for diagnosing a failure in a given test.
+  // Also ignore the very first mismatch, as this identifies two instructions
+  // within the GTest function that called UponLeavingGTest, and is irrelevant
+  // as well.
+  {
+    auto departure_rbegin =
+        std::make_reverse_iterator(departure_addresses + departure_frame_count);
+    auto departure_rend = std::make_reverse_iterator(departure_addresses);
+    auto current_rbegin =
+        std::make_reverse_iterator(current_addresses + current_frame_count);
+    auto current_rend = std::make_reverse_iterator(current_addresses);
+    auto mismatch_pair = std::mismatch(departure_rbegin, departure_rend,
+                                       current_rbegin, current_rend);
+    if (mismatch_pair.second != current_rend)
+      current_frame_count -= (mismatch_pair.second - current_rbegin) + 1;
   }
 
-  // Ignore frames to skip.
-  if (skip_count >= 0 && static_cast<size_t>(skip_count) < frame_count) {
-    frame_count -= skip_count;
-    addresses += skip_count;
+  // Ignore the frames at the leaf of the current trace that match those of the
+  // point of departure from GTest. These frames are the call(s) into
+  // StackTrace's constructor, which are irrelevant. Also ignore the very first
+  // mismatch, as it identifies two instructions within current function.
+  {
+    auto mismatch_pair = std::mismatch(
+        departure_addresses, departure_addresses + departure_frame_count,
+        current_addresses, current_addresses + current_frame_count);
+    if (mismatch_pair.second != current_addresses + current_frame_count) {
+      auto match_size = (mismatch_pair.second - current_addresses) + 1;
+      current_frame_count -= match_size;
+      current_addresses += match_size;
+    }
+  }
+
+  // Ignore frames that the caller wishes to skip.
+  if (skip_count >= 0 &&
+      static_cast<size_t>(skip_count) < current_frame_count) {
+    current_frame_count -= skip_count;
+    current_addresses += skip_count;
   }
 
   // Only return as many as requested.
-  if (max_depth >= 0 && static_cast<size_t>(max_depth) < frame_count)
-    frame_count = static_cast<size_t>(max_depth);
+  if (max_depth >= 0 && static_cast<size_t>(max_depth) < current_frame_count)
+    current_frame_count = static_cast<size_t>(max_depth);
 
-  return base::debug::StackTrace(addresses, frame_count).ToString();
+  return base::debug::StackTrace(current_addresses, current_frame_count)
+      .ToString();
 }
 
 void StackTraceGetter::UponLeavingGTest() {
-  // Remember how deep the stack is as gtest is left.
-  base::debug::StackTrace().Addresses(&frame_count_upon_leaving_gtest_);
-  if (frame_count_upon_leaving_gtest_ > kDepartureSkipFrames)
-    frame_count_upon_leaving_gtest_ -= kDepartureSkipFrames;
+  // Remember the callstack as GTest is left.
+  stack_trace_upon_leaving_gtest_.emplace();
 }
diff --git a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h
index ac33195..5ffa3631 100644
--- a/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h
+++ b/third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h
@@ -5,8 +5,8 @@
 #ifndef THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
 #define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
 
-#include <stddef.h>
-
+#include "base/debug/stack_trace.h"
+#include "base/optional.h"
 #include "third_party/googletest/src/googletest/src/gtest-internal-inl.h"
 
 // An implementation of Google Test's OsStackTraceGetterInterface that uses
@@ -24,7 +24,7 @@
   void UponLeavingGTest() override;
 
  private:
-  size_t frame_count_upon_leaving_gtest_ = 0;
+  base::Optional<base::debug::StackTrace> stack_trace_upon_leaving_gtest_;
 };
 
 #endif  // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
diff --git a/tools/android/roll/android_deps/.gitignore b/tools/android/roll/android_deps/.gitignore
deleted file mode 100644
index ad6be1f..0000000
--- a/tools/android/roll/android_deps/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.gradle/
-.idea/
-.settings/
-local.properties
-buildSrc/.gradle/
-buildSrc/build/
diff --git a/tools/android/roll/android_deps/OWNERS b/tools/android/roll/android_deps/OWNERS
deleted file mode 100644
index 9d8a359..0000000
--- a/tools/android/roll/android_deps/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-agrieve@chromium.org
-jbudorick@chromium.org
-smaier@chromium.org
-wnwen@chromium.org
diff --git a/tools/binary_size/generate_official_build_report.py b/tools/binary_size/generate_official_build_report.py
index 9387260..7d68fe1e 100755
--- a/tools/binary_size/generate_official_build_report.py
+++ b/tools/binary_size/generate_official_build_report.py
@@ -78,9 +78,6 @@
       help='Path to .size file for the given version.')
   parser.add_argument(
       '--arch', required=True, help='Compiler architecture of build.')
-  parser.add_argument('--gs-size-url', help='Unused')
-  parser.add_argument('--gs-size-path', help='Unused')
-  parser.add_argument('--platform', help='Unused')
 
   args = parser.parse_args()
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index d76657f..d5d7f9c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -77,8 +77,8 @@
     },
 
     'chromium.android.fyi': {
+      'Android WebView P Blink-CORS FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_google',
       'Android WebView P FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_google',
-      'Android WebView P OOR-CORS FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_google',
       'android-marshmallow-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_resource_whitelisting',
       'android-pie-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86',
       'android-bfcache-debug': 'android_debug_static_bot',
@@ -206,7 +206,7 @@
       'chromeos-amd64-generic-rel-vm-tests': 'cros_chrome_sdk_dcheck_always_on',
       'chromeos-kevin-rel-hw-tests': 'cros_chrome_sdk',
       'linux-bfcache-debug': 'debug_bot',
-      'linux-oor-cors-rel': 'release_bot_minimal_symbols',
+      'linux-blink-cors-rel': 'release_bot_minimal_symbols',
       'linux-chromeos-code-coverage': 'chromeos_with_codecs_release_bot_coverage',
       'linux-fieldtrial-rel': 'release_bot_minimal_symbols',
       'linux-wpt-fyi-rel': 'release_bot_minimal_symbols',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index ae624f5..bbe24b4 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -10808,6 +10808,7 @@
 </action>
 
 <action name="ManagedUsers_Chromeos_Sync_Invalidated">
+  <obsolete>This metric hasn't triggered since M67</obsolete>
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
 </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 55a006a..871c75fe 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -4994,6 +4994,7 @@
   <int value="27" label="RenderFrameHost is reused for same-site navigation"/>
   <int value="28" label="RenderFrameHost is reused for cross-site navigation"/>
   <int value="29" label="NavigationEntry is not the most recent one"/>
+  <int value="30" label="ServiceWorker claim"/>
 </enum>
 
 <enum name="BackForwardNavigationType">
@@ -6205,6 +6206,11 @@
   <int value="1" label="Timed out"/>
 </enum>
 
+<enum name="BooleanCoalesced">
+  <int value="0" label="not coalesced"/>
+  <int value="1" label="coalesced"/>
+</enum>
+
 <enum name="BooleanColorSpaceSupported">
   <int value="0" label="Color space not supported"/>
   <int value="1" label="Color space supported"/>
@@ -51051,7 +51057,7 @@
   <int value="42" label="REGISTER_PROTOCOL_HANDLER"/>
   <int value="43" label="CREATING_AUDIO_STREAM (Obsolete)"/>
   <int value="44" label="PAGE_BEING_CAPTURED (Obsolete)"/>
-  <int value="45" label="BAD_DEFERRED_REDIRECT"/>
+  <int value="45" label="BAD_DEFERRED_REDIRECT (Obsolete)"/>
   <int value="46" label="NAVIGATION_UNCOMMITTED (Obsolete)"/>
   <int value="47" label="NEW_NAVIGATION_ENTRY (Obsolete)"/>
   <int value="48" label="COOKIE_STORE_NOT_LOADED (Obsolete)"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index aeb3bf3..d30b8a3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1730,7 +1730,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.ExactTaskCreated"
-    enum="BackgroundTaskId" expires_after="2020-01-31">
+    enum="BackgroundTaskId" expires_after="M85">
   <owner>ioanastefan@chromium.org</owner>
   <owner>nator@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
@@ -1783,7 +1783,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskExpired"
-    enum="BackgroundTaskId" expires_after="2020-01-31">
+    enum="BackgroundTaskId" expires_after="M85">
   <owner>ioanastefan@chromium.org</owner>
   <owner>nator@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
@@ -12058,10 +12058,10 @@
 </histogram>
 
 <histogram name="Autofill.ExpirationDateFixFlowPrompt.Events"
-    enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2020-02-01">
+    enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2021-02-01">
   <owner>siashah@google.com</owner>
   <owner>jsaul@google.com</owner>
-  <owner>chrome-autofill@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     Events tracking the usage of the expiration date fix flow prompt. This
     prompt is triggered whenever expiration date must be explicitly requested
@@ -12070,8 +12070,10 @@
 </histogram>
 
 <histogram name="Autofill.ExpirationDateFixFlowPromptShown" enum="Boolean"
-    expires_after="2020-02-01">
+    expires_after="2021-02-01">
   <owner>siashah@google.com</owner>
+  <owner>jsaul@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     The number of times the expiration date fix flow prompt is shown.
   </summary>
@@ -22705,7 +22707,7 @@
   </summary>
 </histogram>
 
-<histogram name="ChromeOS.UrlXattrsCount" units="units" expires_after="M81">
+<histogram name="ChromeOS.UrlXattrsCount" units="units" expires_after="M83">
   <owner>jorgelo@chromium.org</owner>
   <owner>tnagel@chromium.org</owner>
   <summary>
@@ -28487,15 +28489,19 @@
   </summary>
 </histogram>
 
-<histogram name="CrosFirstRun.DialogShown" units="units">
+<histogram name="CrosFirstRun.DialogShown" units="units"
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>
     Records the number of times when first-run dialog was shown.
   </summary>
 </histogram>
 
-<histogram name="CrosFirstRun.FurthestStep" units="units">
+<histogram name="CrosFirstRun.FurthestStep" units="units"
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>
     Index of furthest step that was reached during tutorial. Since order of
     steps could change eventially and new steps could apear we use index here
@@ -28503,25 +28509,30 @@
   </summary>
 </histogram>
 
-<histogram name="CrosFirstRun.TimeSpent" units="ms" expires_after="M81">
+<histogram name="CrosFirstRun.TimeSpent" units="ms" expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>The total time that user spent on first-run tutorial.</summary>
 </histogram>
 
-<histogram name="CrosFirstRun.TimeSpentOnStep" units="ms" expires_after="M81">
+<histogram name="CrosFirstRun.TimeSpentOnStep" units="ms"
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>The time that user spent on some step of tutorial.</summary>
 </histogram>
 
 <histogram name="CrosFirstRun.TutorialCompletion"
-    enum="CrosFirstRunTutorialCompletionType" expires_after="M81">
+    enum="CrosFirstRunTutorialCompletionType" expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>Tracks the way how user left tutorial.</summary>
 </histogram>
 
 <histogram name="CrosFirstRun.TutorialLaunched" units="units"
-    expires_after="M81">
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>
     Records the number of times when first-run tutorial has been launched.
   </summary>
@@ -64383,7 +64394,7 @@
 </histogram>
 
 <histogram name="Login.UsersActiveWeekly" units="users"
-    expires_after="2020-05-31">
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
   <owner>achuith@chromium.org</owner>
   <summary>
@@ -64392,7 +64403,8 @@
   </summary>
 </histogram>
 
-<histogram name="Login.UsersActiveWeekly.Percent" units="%" expires_after="M81">
+<histogram name="Login.UsersActiveWeekly.Percent" units="%"
+    expires_after="2020-12-01">
   <owner>alemate@chromium.org</owner>
   <owner>achuith@chromium.org</owner>
   <summary>
@@ -74895,6 +74907,9 @@
 
 <histogram name="MixedAutoupgrade.Navigation.OptedOut" enum="BooleanOptedOut"
     expires_after="M81">
+  <obsolete>
+    Deprecated as of 01/2020.
+  </obsolete>
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -74904,7 +74919,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.ErrorOrResponseCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2020-02-02">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <summary>
     The net error or HTTP response code of a mixed content resource request that
@@ -74913,7 +74928,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Failure.IsAd" enum="Boolean"
-    expires_after="2020-02-02">
+    expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <summary>
     Whether or not an autoupgrade mixed content request was for a resource we
@@ -74922,7 +74937,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Failure.Type"
-    enum="ResourceType" expires_after="M81">
+    enum="ResourceType" expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -74932,7 +74947,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Response.Type"
-    enum="ResourceType" expires_after="M81">
+    enum="ResourceType" expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -74942,7 +74957,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Start.Type"
-    enum="ResourceType" expires_after="M81">
+    enum="ResourceType" expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -74952,7 +74967,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Status"
-    enum="MixedContentAutoupgradeStatus" expires_after="2020-02-02">
+    enum="MixedContentAutoupgradeStatus" expires_after="M82">
   <owner>carlosil@chromium.org</owner>
   <summary>
     The status of a mixed content resource request that was autoupgraded to
@@ -74962,6 +74977,9 @@
 
 <histogram name="MixedAutoupgrade.Websocket.Status"
     enum="MixedContentAutoupgradeStatus" expires_after="M82">
+  <obsolete>
+    Deprecated as of 01/2020.
+  </obsolete>
   <owner>carlosil@chromium.org</owner>
   <summary>
     The status of a mixed content websocket that was autoupgraded to WSS.
@@ -86136,6 +86154,16 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.CoalesceStreamFrameStatus"
+    enum="BooleanCoalesced" expires_after="2020-11-30">
+  <owner>renjietang@chromium.org</owner>
+  <owner>rch@chromium.org</owner>
+  <summary>
+    When a new stream frame is added to a QUIC packet, record whether it's
+    coalesced with the existing stream frames.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.Connect" units="RTTs">
   <owner>rch@chromium.org</owner>
   <summary>
@@ -102901,6 +102929,36 @@
   </summary>
 </histogram>
 
+<histogram name="Ozone.NeuralStylusReport.ActivePalmTouchCount"
+    units="touch event count" expires_after="2020-09-30">
+  <owner>napper@chromium.org</owner>
+  <owner>robsc@chromium.org</owner>
+  <summary>
+    When a stylus is touched to screen, the number of palms on the device at
+    that time.
+  </summary>
+</histogram>
+
+<histogram name="Ozone.NeuralStylusReport.FingerAgeBeforeStylus"
+    units="duration" expires_after="2020-09-30">
+  <owner>napper@chromium.org</owner>
+  <owner>robsc@chromium.org</owner>
+  <summary>
+    The time between a finger and a stylus touch. The finger may or may not
+    still be on the touchscreen.
+  </summary>
+</histogram>
+
+<histogram name="Ozone.NeuralStylusReport.PalmAgeBeforeStylus" units="duration"
+    expires_after="2020-09-30">
+  <owner>napper@chromium.org</owner>
+  <owner>robsc@chromium.org</owner>
+  <summary>
+    The time between a palm and a stylus touch. The palm may or may not still be
+    on the touchscreen.
+  </summary>
+</histogram>
+
 <histogram name="Ozone.TouchEventConverterEvdev.HoldCountAtCancel"
     units="touch event" expires_after="2020-12-01">
   <owner>robsc@chromium.org</owner>
@@ -105690,7 +105748,7 @@
 </histogram>
 
 <histogram name="PageLoad.FrameCounts.AdFrames.PerFrame.UserActivation"
-    enum="AdUserActivationStatus" expires_after="2020-01-17">
+    enum="AdUserActivationStatus" expires_after="2021-01-17">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -137154,8 +137212,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.Fallback.Time" units="ms"
-    expires_after="M81">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken between dispatching a FetchEvent to a Service Worker and
     receiving a fallback-to-network reply.
@@ -137163,8 +137222,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.HasResponse.Time" units="ms"
-    expires_after="2020-04-19">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken between dispatching a FetchEvent to a Service Worker and
     receiving a response. Includes the time for the respondWith() promise to
@@ -137960,8 +138020,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.RegisteredOriginCount" units="origins"
-    expires_after="M81">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The number of origins that have a service worker registration. Recorded near
     browser startup, when the service worker storage system is initialized.
@@ -138106,8 +138167,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartNewWorker.Time" units="ms"
-    expires_after="M81">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken to start a Service Worker that has not yet installed, from
     process allocation to ACK of started from the renderer (which occurs after
@@ -138259,8 +138321,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.AfterFailureStreak"
-    enum="ServiceWorkerStatusCode" expires_after="M81">
+    enum="ServiceWorkerStatusCode" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The result of trying to start a service worker after it has failed
     consecutively. Recorded only for installed workers.
@@ -138268,8 +138331,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.FailureStreak" units="count"
-    expires_after="M81">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The number of consecutive startup failures of a service worker. Recorded
     each time the service worker failed (so there is double counting: failing
@@ -138278,8 +138342,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.FailureStreakEnded" units="count"
-    expires_after="2020-07-30">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     When a worker startup succeeded after failing, the number of times the
     worker had consecutively failed. Recorded only for installed workers.
@@ -138304,8 +138369,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.Purpose"
-    enum="ServiceWorkerMetrics.EventType" expires_after="2020-07-30">
+    enum="ServiceWorkerMetrics.EventType" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The purpose for starting up a service worker. Recorded only for installed
     workers.
@@ -138313,8 +138379,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.Status"
-    enum="ServiceWorkerStatusCode" expires_after="2020-04-19">
+    enum="ServiceWorkerStatusCode" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The result of trying to start a Service Worker that is already installed.
     See also ServiceWorker.StartNewWorker.Status for new workers. See also
@@ -138323,8 +138390,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.StatusByPurpose"
-    enum="ServiceWorkerStatusCode" expires_after="2020-02-16">
+    enum="ServiceWorkerStatusCode" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The result of trying to start a service worker for a particular event type
     (see ServiceWorker.StartWorker.Status for the total). Only recorded for
@@ -138333,8 +138401,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.Time" units="ms"
-    expires_after="2020-04-19">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken to start a Service Worker that is already installed, from
     process allocation to ACK of started from the renderer (which occurs after
@@ -138345,8 +138414,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.Timeout.StartPurpose"
-    enum="ServiceWorkerMetrics.EventType" expires_after="M81">
+    enum="ServiceWorkerMetrics.EventType" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     Records the start purpose for a service worker that timed out while starting
     up. Recorded only for installed workers.
@@ -138354,8 +138424,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.StartWorker.TimeoutPhase"
-    enum="EmbeddedWorkerStartingPhase" expires_after="2020-02-16">
+    enum="EmbeddedWorkerStartingPhase" expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The phase the EmbeddedWorker was in when ServiceWorker startup timed out.
   </summary>
@@ -138569,8 +138640,9 @@
 </histogram>
 
 <histogram name="ServiceWorker.WorkerStopped" enum="ServiceWorkerStoppedStatus"
-    expires_after="M81">
+    expires_after="2021-01-31">
   <owner>falken@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The mechanism by which a service worker entered running status STOPPED.
   </summary>
diff --git a/tools/metrics/histograms/pretty_print.py b/tools/metrics/histograms/pretty_print.py
index 0ea2e84..90194ab 100755
--- a/tools/metrics/histograms/pretty_print.py
+++ b/tools/metrics/histograms/pretty_print.py
@@ -75,19 +75,57 @@
   if obsoletes:
     tree.insert(0, obsoletes[0])
 
-def DropNodesByTagName(tree, tag):
+def DropNodesByTagName(tree, tag, dropped_nodes=[]):
   """Drop all nodes with named tag from the XML tree."""
   removes = []
 
   for child in tree:
     if child.tag == tag:
       removes.append(child)
+      dropped_nodes.append(child)
     else:
       DropNodesByTagName(child, tag)
 
   for child in removes:
     tree.remove(child)
 
+def FixMisplacedHistogramsAndHistogramSuffixes(tree):
+  """Fixes misplaced histogram and histogram_suffixes nodes."""
+  histograms = []
+  histogram_suffixes = []
+
+  def ExtractMisplacedHistograms(tree):
+    """Gets and drops misplaced histograms and histogram_suffixes.
+
+    Args:
+      tree: The node of the xml tree.
+      histograms: A list of histogram nodes inside histogram_suffixes_list
+          node. This is a return element.
+      histogram_suffixes: A list of histogram_suffixes nodes inside hisotgrams
+          node. This is a return element.
+    """
+    for child in tree:
+      if child.tag == 'histograms':
+        DropNodesByTagName(child, 'histogram_suffixes', histogram_suffixes)
+      elif child.tag == 'histogram_suffixes_list':
+        DropNodesByTagName(child, 'histogram', histograms)
+      else:
+        ExtractMisplacedHistograms(child)
+
+  ExtractMisplacedHistograms(tree)
+
+  def AddBackMisplacedHisotgrams(tree):
+    """Adds back those misplaced histogram and hsitogram_suffixes nodes."""
+    for child in tree:
+      if child.tag == 'histograms':
+        child.extend(histograms)
+      elif child.tag == 'histogram_suffixes_list':
+        child.extend(histogram_suffixes)
+      else:
+        FixMisplacedHisotgrams(child)
+
+  AddBackMisplacedHisotgrams(tree)
+
 def PrettyPrintHistograms(raw_xml):
   """Pretty-print the given histograms XML.
 
@@ -112,6 +150,7 @@
   """
   # Prevent accidentally adding enums to histograms.xml
   DropNodesByTagName(tree, 'enums')
+  FixMisplacedHistogramsAndHistogramSuffixes(tree)
   canonicalizeUnits(tree)
   fixObsoleteOrder(tree)
   return histograms_print_style.GetPrintStyle().PrettyPrintXml(tree)
diff --git a/tools/metrics/histograms/pretty_print_test.py b/tools/metrics/histograms/pretty_print_test.py
index b3530a5..7936363 100755
--- a/tools/metrics/histograms/pretty_print_test.py
+++ b/tools/metrics/histograms/pretty_print_test.py
@@ -25,6 +25,7 @@
        Removed 1/2019.
    </obsolete>
  </histogram>
+
  <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz">
   <summary>Foo</summary>
   <obsolete>Obsolete 1</obsolete>
@@ -33,12 +34,29 @@
   <component>Component</component>
   <component>Other&gt;Component</component>
  </histogram>
+
+ <histogram_suffixes name="Test.HistogramSuffixes" separator=".">
+  <suffix name="TestSuffix" label="A misplaced histogram_suffixes"/>
+  <affected-histogram name="Test.Histogram"/>
+</histogram_suffixes>
+
 </histograms>
+
+<histogram_suffixes_list>
+
+<histogram name="Test.MisplacedHistogram" units="us">
+   <owner>person@chromium.org</owner>
+   <summary>A misplaced histogram
+   </summary>
+   Misplaced content.
+ </histogram>
+
+</histogram_suffixes_list>
+
 <enums>This shouldn't be here</enums>
 </histogram-configuration>
 """.strip()
 
-
 PRETTY_XML = """
 <!-- Top level Comment 1 -->
 <!-- Top level Comment 2 -->
@@ -70,8 +88,23 @@
   Mixed content.
 </histogram>
 
+<histogram name="Test.MisplacedHistogram" units="microseconds">
+  <owner>person@chromium.org</owner>
+  <summary>A misplaced histogram</summary>
+  Misplaced content.
+</histogram>
+
 </histograms>
 
+<histogram_suffixes_list>
+
+<histogram_suffixes name="Test.HistogramSuffixes" separator=".">
+  <suffix name="TestSuffix" label="A misplaced histogram_suffixes"/>
+  <affected-histogram name="Test.Histogram"/>
+</histogram_suffixes>
+
+</histogram_suffixes_list>
+
 </histogram-configuration>
 """.strip()
 
diff --git a/tools/perf/BUILD.gn b/tools/perf/BUILD.gn
index 956e1f3..c4736fa 100644
--- a/tools/perf/BUILD.gn
+++ b/tools/perf/BUILD.gn
@@ -8,10 +8,6 @@
   deps = [
     "//tools/perf/chrome_telemetry_build:telemetry_chrome_test",
   ]
-  data_deps = [
-    "//third_party/perfetto/src/trace_processor:trace_processor_shell",
-  ]
-
   data = [
     "//tools/perf/",
 
@@ -39,7 +35,9 @@
 
   # Runs a script which generates the ad tagging ruleset.
   if (!is_ios) {
-    data_deps += [ "//components/subresource_filter/tools:index_ruleset" ]
+    data_deps = [
+      "//components/subresource_filter/tools:index_ruleset",
+    ]
   }
 }
 
diff --git a/tools/perf/benchmark_schedules.csv b/tools/perf/benchmark_schedules.csv
index 3a2d39a..99af6d52 100644
--- a/tools/perf/benchmark_schedules.csv
+++ b/tools/perf/benchmark_schedules.csv
@@ -17,7 +17,6 @@
 rasterize_and_record_micro.top_25,2.55,12,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.bindings,2.40,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.parser,1.69,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
-angle_perftests,1.66,3,0,"Win 7 Nvidia GPU Perf, android-pixel2-perf, win-10-perf",
 blink_perf.canvas,1.43,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.css,1.08,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 webrtc,1.01,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
@@ -30,6 +29,7 @@
 speedometer2-future,0.66,12,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.dom,0.64,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 dromaeo,0.57,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
+angle_perftests,0.55,1,0,android-pixel2-perf,
 blink_perf.svg,0.54,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.events,0.53,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 speedometer2,0.48,14,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-go-perf, android-go_webview-perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
@@ -45,19 +45,12 @@
 octane,0.21,12,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.accessibility,0.18,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 speedometer-future,0.11,11,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf",
-components_perftests,0.09,3,0,"Android Nexus5 Perf, Win 7 Perf, win-10-perf",
-dawn_perf_tests,0.07,1,0,win-10-perf,
-base_perftests,0.07,1,0,win-10-perf,
 rasterize_and_record_micro.partial_invalidation,0.05,12,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 dummy_benchmark.stable_benchmark_1,0.03,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 dummy_benchmark.noisy_benchmark_1,0.03,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
+components_perftests,0.03,1,0,Android Nexus5 Perf,
 system_health.webview_startup,0.03,4,0,"Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, android-go_webview-perf, android-pixel2_webview-perf",
 gpu_perftests,0.02,1,0,Android Nexus5 Perf,
 tracing_perftests,0.01,1,0,Android Nexus5 Perf,
-media_perftests,0.01,3,0,"Win 7 Nvidia GPU Perf, Win 7 Perf, win-10-perf",
-passthrough_command_buffer_perftests,0.01,1,0,Win 7 Nvidia GPU Perf,
-validating_command_buffer_perftests,0.01,1,0,Win 7 Nvidia GPU Perf,
-views_perftests,0.00,1,0,win-10-perf,
-load_library_perf_tests,0.00,2,0,"Win 7 Nvidia GPU Perf, Win 7 Perf",
 v8.browsing_mobile-future,0.00,6,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf",
 tab_switching.typical_25,0.00,7,0,"Win 7 Nvidia GPU Perf, Win 7 Perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index a1bca3c3..4788811 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -70,6 +70,7 @@
   'system_health.memory_mobile/load:media:facebook_photos',
   'system_health.memory_mobile/load:media:dailymotion',
   'system_health.memory_mobile/load:news:cnn',
+  'system_health.memory_mobile/load:news:irctc',
   'system_health.memory_mobile/load:news:nytimes',
   'system_health.memory_mobile/load:news:qq',
   'system_health.memory_mobile/load:news:reddit',
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 280de1a..9d59c57 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -16,6 +16,7 @@
 
   data_deps = [
     ":telemetry_chrome_test_without_chrome",
+    "//third_party/perfetto/src/trace_processor:trace_processor_shell",
   ]
   data = []
 
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index 8dbe995..62d2f7a 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -359,13 +359,13 @@
     'win-10-perf',
     'Windows Intel HD 630 towers, Core i7-7700 3.6 GHz, 16GB RAM,'
     ' Intel Kaby Lake HD Graphics 630', _WIN_10_BENCHMARK_CONFIGS,
-    26, 'win', executables=_WIN_10_EXECUTABLE_CONFIGS)
+    26, 'win')#, executables=_WIN_10_EXECUTABLE_CONFIGS) crbug.com/1039019
 WIN_7 = PerfPlatform(
     'Win 7 Perf', 'N/A', _WIN_7_BENCHMARK_CONFIGS,
-    4, 'win', executables=_WIN_7_EXECUTABLE_CONFIGS)
+    4, 'win')#, executables=_WIN_7_EXECUTABLE_CONFIGS) crbug.com/1039019
 WIN_7_GPU = PerfPlatform(
     'Win 7 Nvidia GPU Perf', 'N/A', _WIN_7_GPU_BENCHMARK_CONFIGS,
-    4, 'win', executables=_WIN_7_GPU_EXECUTABLE_CONFIGS)
+    4, 'win')#, executables=_WIN_7_GPU_EXECUTABLE_CONFIGS) crbug.com/1039019
 
 # Android
 ANDROID_GO = PerfPlatform(
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 37d18e2..0ba9c5f 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -392,14 +392,6 @@
         'type': TEST_TYPES.GTEST,
       },
       {
-        'isolate': 'angle_perftests',
-        'num_shards': 1,
-        'type': TEST_TYPES.GTEST,
-        'extra_args': [
-            '--shard-timeout=300'
-        ],
-      },
-      {
         'isolate': 'base_perftests',
         'num_shards': 1,
         'type': TEST_TYPES.GTEST,
@@ -545,6 +537,44 @@
             '--assert-gpu-compositing',
         ],
       },
+      # TODO(crbug.com/1039019): Remove all of the following gtests and enable
+      # as part of the shard maps.
+      {
+        'isolate': 'angle_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+        'extra_args': [
+            '--shard-timeout=300'
+        ],
+      },
+      {
+        'isolate': 'media_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'components_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'views_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'base_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'dawn_perf_tests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+        'extra_args': [
+            '--shard-timeout=300'
+        ],
+      },
     ],
     'platform': 'win',
     'target_bits': 64,
@@ -564,6 +594,23 @@
       {
         'isolate': 'performance_test_suite',
       },
+      # TODO(crbug.com/1039019): Remove all of the following gtests and enable
+      # as part of the shard maps.
+      {
+        'isolate': 'load_library_perf_tests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'components_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'media_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      }
     ],
     'platform': 'win',
     'target_bits': 32,
@@ -582,6 +629,43 @@
             '--assert-gpu-compositing',
         ],
       },
+      # TODO(crbug.com/1039019): Remove all of the following gtests and enable
+      # as part of the shard maps.
+      {
+        'isolate': 'load_library_perf_tests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'angle_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'isolate': 'media_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
+      {
+        'name': 'passthrough_command_buffer_perftests',
+        'isolate': 'command_buffer_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+        'extra_args': [
+            '--use-cmd-decoder=passthrough',
+            '--use-angle=gl-null',
+        ],
+      },
+      {
+        'name': 'validating_command_buffer_perftests',
+        'isolate': 'command_buffer_perftests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+        'extra_args': [
+            '--use-cmd-decoder=validating',
+            '--use-stub',
+        ],
+      },
     ],
     'platform': 'win',
     'target_bits': 64,
diff --git a/tools/perf/core/shard_maps/timing_data/win-10-perf_timing.json b/tools/perf/core/shard_maps/timing_data/win-10-perf_timing.json
index e3b53bad9..5af3e72 100644
--- a/tools/perf/core/shard_maps/timing_data/win-10-perf_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/win-10-perf_timing.json
@@ -4662,29 +4662,5 @@
     {
         "duration": "52.0",
         "name": "webrtc/pause_play_peerconnections"
-    },
-    {
-        "duration": "16.0",
-        "name": "media_perftests/_gtest_"
-    },
-    {
-        "duration": "7.0",
-        "name": "views_perftests/_gtest_"
-    },
-    {
-        "duration": "270.0",
-        "name": "base_perftests/_gtest_"
-    },
-    {
-        "duration": "270.0",
-        "name": "dawn_perf_tests/_gtest_"
-    },
-    {
-        "duration": "1988.0",
-        "name": "angle_perftests/_gtest_"
-    },
-    {
-        "duration": "110.0",
-        "name": "components_perftests/_gtest_"
     }
 ]
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/win_7_nvidia_gpu_perf_timing.json b/tools/perf/core/shard_maps/timing_data/win_7_nvidia_gpu_perf_timing.json
index f8ccdd4..288402e 100644
--- a/tools/perf/core/shard_maps/timing_data/win_7_nvidia_gpu_perf_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/win_7_nvidia_gpu_perf_timing.json
@@ -4658,25 +4658,5 @@
     {
         "duration": "41.0",
         "name": "webrtc/pause_play_peerconnections"
-    },
-    {
-        "duration": "30.0",
-        "name": "passthrough_command_buffer_perftests/_gtest_"
-    },
-    {
-        "duration": "1988.0",
-        "name": "angle_perftests/_gtest_"
-    },
-    {
-        "duration": "16.0",
-        "name": "media_perftests/_gtest_"
-    },
-    {
-        "duration": "3.0",
-        "name": "load_library_perf_tests/_gtest_"
-    },
-    {
-        "duration": "23.0",
-        "name": "validating_command_buffer_perftests/_gtest_"
     }
 ]
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/win_7_perf_timing.json b/tools/perf/core/shard_maps/timing_data/win_7_perf_timing.json
index cb23a51..64502ca 100644
--- a/tools/perf/core/shard_maps/timing_data/win_7_perf_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/win_7_perf_timing.json
@@ -3122,17 +3122,5 @@
     {
         "duration": "45.0",
         "name": "webrtc/pause_play_peerconnections"
-    },
-    {
-        "duration": "110.0",
-        "name": "components_perftests/_gtest_"
-    },
-    {
-        "duration": "16.0",
-        "name": "media_perftests/_gtest_"
-    },
-    {
-        "duration": "3.0",
-        "name": "load_library_perf_tests/_gtest_"
     }
 ]
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/win-10-perf_map.json b/tools/perf/core/shard_maps/win-10-perf_map.json
index 6061fb52..121a1e7 100644
--- a/tools/perf/core/shard_maps/win-10-perf_map.json
+++ b/tools/perf/core/shard_maps/win-10-perf_map.json
@@ -1,12 +1,8 @@
 {
     "0": {
-        "executables": {
-            "angle_perftests": {
-                "path": "angle_perftests",
-                "arguments": [
-                    "--test-launcher-retry-limit=0",
-                    "--test-launcher-jobs=1"
-                ]
+        "benchmarks": {
+            "dummy_benchmark.noisy_benchmark_1": {
+                "abridged": false
             }
         }
     },
@@ -19,15 +15,6 @@
                 "end": 27,
                 "abridged": false
             }
-        },
-        "executables": {
-            "base_perftests": {
-                "path": "base_perftests",
-                "arguments": [
-                    "--test-launcher-jobs=1",
-                    "--test-launcher-retry-limit=0"
-                ]
-            }
         }
     },
     "2": {
@@ -90,9 +77,6 @@
             "dromaeo": {
                 "abridged": false
             },
-            "dummy_benchmark.noisy_benchmark_1": {
-                "abridged": false
-            },
             "dummy_benchmark.stable_benchmark_1": {
                 "abridged": false
             },
@@ -109,21 +93,6 @@
                 "end": 12,
                 "abridged": false
             }
-        },
-        "executables": {
-            "components_perftests": {
-                "path": "components_perftests",
-                "arguments": [
-                    "--xvfb"
-                ]
-            },
-            "dawn_perf_tests": {
-                "path": "dawn_perf_tests",
-                "arguments": [
-                    "--test-launcher-jobs=1",
-                    "--test-launcher-retry-limit=0"
-                ]
-            }
         }
     },
     "5": {
@@ -157,16 +126,6 @@
                 "end": 4,
                 "abridged": false
             }
-        },
-        "executables": {
-            "media_perftests": {
-                "path": "media_perftests",
-                "arguments": [
-                    "--single-process-tests",
-                    "--test-launcher-retry-limit=0",
-                    "--isolated-script-test-filter=*::-*_unoptimized::*_unaligned::*unoptimized_aligned"
-                ]
-            }
         }
     },
     "8": {
@@ -369,14 +328,6 @@
             "webrtc": {
                 "abridged": false
             }
-        },
-        "executables": {
-            "views_perftests": {
-                "path": "views_perftests",
-                "arguments": [
-                    "--xvfb"
-                ]
-            }
         }
     },
     "extra_infos": {
diff --git a/tools/perf/core/shard_maps/win_7_nvidia_gpu_perf_map.json b/tools/perf/core/shard_maps/win_7_nvidia_gpu_perf_map.json
index 946160f2..7aad40fd 100644
--- a/tools/perf/core/shard_maps/win_7_nvidia_gpu_perf_map.json
+++ b/tools/perf/core/shard_maps/win_7_nvidia_gpu_perf_map.json
@@ -59,18 +59,6 @@
                 "end": 86,
                 "abridged": false
             }
-        },
-        "executables": {
-            "angle_perftests": {
-                "path": "angle_perftests",
-                "arguments": [
-                    "--test-launcher-retry-limit=0",
-                    "--test-launcher-jobs=1"
-                ]
-            },
-            "load_library_perf_tests": {
-                "path": "load_library_perf_tests"
-            }
         }
     },
     "1": {
@@ -116,23 +104,6 @@
                 "end": 5,
                 "abridged": false
             }
-        },
-        "executables": {
-            "media_perftests": {
-                "path": "media_perftests",
-                "arguments": [
-                    "--single-process-tests",
-                    "--test-launcher-retry-limit=0",
-                    "--isolated-script-test-filter=*::-*_unoptimized::*_unaligned::*unoptimized_aligned"
-                ]
-            },
-            "passthrough_command_buffer_perftests": {
-                "path": "command_buffer_perftests",
-                "arguments": [
-                    "--use-cmd-decoder=passthrough",
-                    "--use-angle=gl-null"
-                ]
-            }
         }
     },
     "2": {
@@ -171,15 +142,6 @@
             "webrtc": {
                 "abridged": false
             }
-        },
-        "executables": {
-            "validating_command_buffer_perftests": {
-                "path": "command_buffer_perftests",
-                "arguments": [
-                    "--use-cmd-decoder=validating",
-                    "--use-stub"
-                ]
-            }
         }
     },
     "extra_infos": {
diff --git a/tools/perf/core/shard_maps/win_7_perf_map.json b/tools/perf/core/shard_maps/win_7_perf_map.json
index 60231568..295d602b 100644
--- a/tools/perf/core/shard_maps/win_7_perf_map.json
+++ b/tools/perf/core/shard_maps/win_7_perf_map.json
@@ -59,17 +59,6 @@
                 "end": 77,
                 "abridged": false
             }
-        },
-        "executables": {
-            "components_perftests": {
-                "path": "components_perftests",
-                "arguments": [
-                    "--xvfb"
-                ]
-            },
-            "load_library_perf_tests": {
-                "path": "load_library_perf_tests"
-            }
         }
     },
     "1": {
@@ -115,16 +104,6 @@
                 "end": 39,
                 "abridged": false
             }
-        },
-        "executables": {
-            "media_perftests": {
-                "path": "media_perftests",
-                "arguments": [
-                    "--single-process-tests",
-                    "--test-launcher-retry-limit=0",
-                    "--isolated-script-test-filter=*::-*_unoptimized::*_unaligned::*unoptimized_aligned"
-                ]
-            }
         }
     },
     "2": {
diff --git a/tools/perf/cycletime_contributions.csv b/tools/perf/cycletime_contributions.csv
index aed8b3d..ae2f94f 100644
--- a/tools/perf/cycletime_contributions.csv
+++ b/tools/perf/cycletime_contributions.csv
@@ -2,9 +2,8 @@
 View a prettier version of this at,https://docs.google.com/spreadsheets/d/15pJY4cxtM2NVNFKQDgDnoT5PLo0Nm5Td-Ov-5PZefAw
 platform,Android Nexus5 Perf,Android Nexus5X WebView Perf,Android Nexus6 WebView Perf,Win 7 Nvidia GPU Perf,Win 7 Perf,android-go-perf,android-go_webview-perf,android-nexus5x-perf,android-pixel2-perf,android-pixel2_weblayer-perf,android-pixel2_webview-perf,linux-perf,mac-10_12_laptop_low_end-perf,mac-10_13_laptop_high_end-perf,win-10-perf,win-10_laptop_low_end-perf
 shards,16,16,12,4,4,19,13,10,35,4,21,26,26,26,26,26
-idealized cycle time (hours),2.24,0.56,0.76,3.45,2.45,0.70,0.26,1.37,0.60,0.15,0.34,0.39,0.43,0.33,0.55,0.70
-angle_perftests,0.000,0.000,0.000,0.276,0.000,0.000,0.000,0.000,0.032,0.000,0.000,0.000,0.000,0.000,0.042,0.000
-base_perftests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.006,0.000
+idealized cycle time (hours),2.24,0.56,0.76,3.17,2.43,0.70,0.26,1.37,0.60,0.15,0.34,0.39,0.43,0.33,0.50,0.70
+angle_perftests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.032,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 blink_perf.accessibility,0.003,0.001,0.001,0.005,0.006,0.000,0.000,0.003,0.001,0.000,0.001,0.001,0.001,0.001,0.001,0.001
 blink_perf.bindings,0.052,0.014,0.029,0.052,0.061,0.000,0.000,0.050,0.013,0.000,0.009,0.006,0.009,0.007,0.008,0.011
 blink_perf.canvas,0.036,0.000,0.012,0.067,0.020,0.000,0.000,0.000,0.010,0.000,0.005,0.006,0.010,0.008,0.008,0.010
@@ -19,8 +18,7 @@
 blink_perf.parser,0.042,0.011,0.017,0.034,0.039,0.000,0.000,0.043,0.008,0.000,0.006,0.004,0.006,0.005,0.005,0.006
 blink_perf.shadow_dom,0.037,0.000,0.011,0.020,0.024,0.000,0.000,0.000,0.008,0.000,0.004,0.001,0.003,0.002,0.004,0.004
 blink_perf.svg,0.016,0.002,0.006,0.010,0.012,0.000,0.000,0.011,0.004,0.000,0.002,0.001,0.001,0.001,0.002,0.002
-components_perftests,0.004,0.000,0.000,0.000,0.015,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.002,0.000
-dawn_perf_tests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.006,0.000
+components_perftests,0.004,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 dromaeo,0.007,0.003,0.004,0.020,0.020,0.000,0.000,0.010,0.003,0.000,0.002,0.002,0.003,0.003,0.003,0.003
 dummy_benchmark.noisy_benchmark_1,0.001,0.000,0.000,0.000,0.001,0.000,0.000,0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 dummy_benchmark.stable_benchmark_1,0.001,0.001,0.000,0.000,0.001,0.000,0.000,0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
@@ -28,15 +26,12 @@
 jetstream,0.000,0.000,0.000,0.024,0.027,0.000,0.000,0.000,0.000,0.000,0.000,0.004,0.004,0.004,0.004,0.005
 jetstream2,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.008,0.000,0.000,0.003,0.000,0.004,0.003,0.007
 kraken,0.006,0.002,0.002,0.003,0.004,0.000,0.000,0.006,0.001,0.000,0.001,0.000,0.001,0.001,0.001,0.001
-load_library_perf_tests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 loading.desktop,0.000,0.000,0.000,0.218,0.172,0.000,0.000,0.000,0.000,0.000,0.000,0.022,0.037,0.023,0.034,0.056
 loading.mobile,0.094,0.021,0.029,0.000,0.000,0.000,0.000,0.085,0.026,0.000,0.014,0.000,0.000,0.000,0.000,0.000
 media.desktop,0.000,0.000,0.000,0.055,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.007,0.009,0.007,0.009,0.012
 media.mobile,0.025,0.000,0.000,0.000,0.000,0.000,0.000,0.027,0.006,0.000,0.000,0.000,0.000,0.000,0.000,0.000
-media_perftests,0.000,0.000,0.000,0.002,0.002,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 memory.desktop,0.000,0.000,0.000,0.031,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.003,0.004,0.003,0.005,0.005
 octane,0.005,0.001,0.002,0.005,0.000,0.000,0.000,0.005,0.001,0.000,0.001,0.001,0.001,0.001,0.001,0.001
-passthrough_command_buffer_perftests,0.000,0.000,0.000,0.004,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 power.desktop,0.000,0.000,0.000,0.076,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.012,0.013,0.011,0.013,0.016
 rasterize_and_record_micro.partial_invalidation,0.001,0.000,0.001,0.001,0.000,0.000,0.000,0.002,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 rasterize_and_record_micro.top_25,0.049,0.016,0.025,0.083,0.000,0.000,0.000,0.056,0.013,0.000,0.010,0.008,0.009,0.009,0.013,0.017
@@ -60,6 +55,4 @@
 v8.browsing_mobile,0.338,0.072,0.079,0.000,0.000,0.255,0.000,0.339,0.061,0.000,0.041,0.000,0.000,0.000,0.000,0.000
 v8.browsing_mobile-future,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 v8.runtime_stats.top_25,0.000,0.000,0.000,0.613,0.805,0.000,0.000,0.000,0.000,0.000,0.000,0.079,0.000,0.000,0.094,0.116
-validating_command_buffer_perftests,0.000,0.000,0.000,0.003,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
-views_perftests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000
 webrtc,0.017,0.004,0.006,0.034,0.038,0.000,0.000,0.016,0.004,0.000,0.003,0.004,0.005,0.004,0.005,0.010
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index d719812..ac363f5 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -232,6 +232,7 @@
 crbug.com/755556 [ mac ] rendering.desktop/mix_blend_mode_animation_hue [ Skip ]
 crbug.com/1017244 [ desktop ] rendering.desktop/youtube_2018 [ Skip ]
 crbug.com/1017244 [ desktop ] rendering.desktop/youtube_pinch_2018 [ Skip ]
+crbug.com/1039283 [ desktop ] rendering.desktop/gmail_move_2018 [ Skip ]
 
 # Benchmark: rendering.mobile
 crbug.com/785485 [ android-webview ] rendering.mobile/kevs_3d [ Skip ]
@@ -277,7 +278,10 @@
 crbug.com/1017244 [ mobile ] rendering.mobile/youtube_2018 [ Skip ]
 crbug.com/1036357 [ android-nexus-5 ] rendering.mobile/idle_power_blank [ Skip ]
 crbug.com/1036357 [ android-nexus-5 ] rendering.mobile/balls_svg_animations [ Skip ]
-
+crbug.com/1039281 [ android ] rendering.mobile/linkedin_mobile_2018 [ Skip ]
+crbug.com/1039281 [ android ] rendering.mobile/linkedin_mobile_pinch_2018 [ Skip ]
+crbug.com/1039281 [ android ] rendering.mobile/linkedin_pathological_2018 [ Skip ]
+crbug.com/1039344 [ android-nexus-5x android-webview ] rendering.mobile/canvas_animation_no_clear [ Skip ]
 
 # Benchmark: rasterize_and_record_micro.top_25
 crbug.com/764543 rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
@@ -345,6 +349,7 @@
 crbug.com/1036141 [ android-webview ] system_health.common_mobile/browse:shopping:lazada:2019 [ Skip ]
 crbug.com/1036143 [ android-pixel-2 ] system_health.common_mobile/browse:chrome:omnibox:2019 [ Skip ]
 crbug.com/1037687 [ android ] system_health.common_mobile/browse:social:pinterest_infinite_scroll:2019 [ Skip ]
+crbug.com/1039277 [ android ] system_health.common_mobile/load:tools:dropbox:2019 [ Skip ]
 
 # Benchmark: system_health.memory_desktop
 crbug.com/1027686 [ linux ] system_health.memory_desktop/browse:social:tumblr_infinite_scroll:2018 [ Skip ]
@@ -424,6 +429,7 @@
 crbug.com/1017661 [ android-nexus-5x ] system_health.memory_mobile/browse:tech:discourse_infinite_scroll:2018 [ Skip ]
 crbug.com/1036143 [ android-pixel-2 ] system_health.memory_mobile/browse:chrome:omnibox:2019 [ Skip ]
 crbug.com/1037687 [ android ] system_health.memory_mobile/browse:social:pinterest_infinite_scroll:2019 [ Skip ]
+crbug.com/1039277 [ android ] system_health.memory_mobile/load:tools:dropbox:2019 [ Skip ]
 
 # Benchmark: tab_switching.typical_25
 crbug.com/747026 [ mac ] tab_switching.typical_25/multitab:misc:typical24 [ Skip ]
@@ -478,6 +484,8 @@
 crbug.com/1036143 [ android-pixel-2 ] v8.browsing_mobile/browse:chrome:omnibox:2019 [ Skip ]
 crbug.com/1037687 [ android ] v8.browsing_mobile/browse:social:pinterest_infinite_scroll:2019 [ Skip ]
 crbug.com/1037905 [ android-nexus-6 android-webview ] v8.browsing_mobile/browse:media:imgur:2019 [ Skip ]
+crbug.com/1039295 [ android-go ] v8.browsing_mobile/browse:news:nytimes:2019 [ Skip ]
+crbug.com/1039295 [ android-nexus-5 ] v8.browsing_mobile/browse:news:nytimes:2019 [ Skip ]
 
 # Benchmark: v8.browsing_mobile-future
 # Disabled v8.browsing_mobile-future for capacity reasons while we update
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json
index 69eadc04..de615e7 100644
--- a/tools/perf/page_sets/data/system_health_mobile.json
+++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -276,6 +276,9 @@
         "load:news:irctc": {
             "DEFAULT": "system_health_mobile_058.wprgo"
         },
+        "load:news:irctc:2019": {
+            "DEFAULT": "system_health_mobile_941a515134.wprgo"
+        },
         "load:news:nytimes": {
             "DEFAULT": "system_health_mobile_009.wprgo"
         },
diff --git a/tools/perf/page_sets/data/system_health_mobile_941a515134.wprgo.sha1 b/tools/perf/page_sets/data/system_health_mobile_941a515134.wprgo.sha1
new file mode 100644
index 0000000..7aaba5b
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_941a515134.wprgo.sha1
@@ -0,0 +1 @@
+941a5151345ef7a718af77425ff137f89c7098e3
\ 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 2c1abdc..4bf11a0 100644
--- a/tools/perf/page_sets/system_health/loading_stories.py
+++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -327,6 +327,19 @@
   TAGS = [story_tags.EMERGING_MARKET, story_tags.HEALTH_CHECK,
           story_tags.YEAR_2016]
 
+class LoadIrctcStory2019(_LoadingStory):
+  NAME = 'load:news:irctc:2019'
+  URL = 'https://www.irctc.co.in'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  TAGS = [story_tags.EMERGING_MARKET, story_tags.HEALTH_CHECK,
+          story_tags.YEAR_2019]
+
+  def _Login(self, action_runner):
+    # There is an error on replay that pops up the first time. If we
+    # navigate again, the error disappears.
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+    action_runner.Navigate(self.URL)
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
 
 ################################################################################
 # Audio, images, and video.
diff --git a/tools/perf/system_health_stories.csv b/tools/perf/system_health_stories.csv
index aa5c238..240e7e8a 100644
--- a/tools/perf/system_health_stories.csv
+++ b/tools/perf/system_health_stories.csv
@@ -102,6 +102,7 @@
 load:news:flipboard,,desktop,2016
 load:news:hackernews:2018,,desktop,2018
 load:news:irctc,,mobile,"2016,emerging_market,health_check"
+load:news:irctc:2019,,mobile,"2019,emerging_market,health_check"
 load:news:nytimes,,mobile,"2016,health_check"
 load:news:nytimes:2018,,desktop,2018
 load:news:nytimes:2019,,mobile,"2019,health_check"
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 9470d3ab..a51cbdce 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -62,8 +62,6 @@
     "ax_export.h",
     "ax_language_detection.cc",
     "ax_language_detection.h",
-    "ax_live_region_tracker.cc",
-    "ax_live_region_tracker.h",
     "ax_mode.cc",
     "ax_mode.h",
     "ax_mode_observer.h",
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index b0c41170..106364a 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -8,7 +8,6 @@
 
 #include "base/stl_util.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_live_region_tracker.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
 
@@ -101,10 +100,8 @@
 AXEventGenerator::AXEventGenerator() = default;
 
 AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) {
-  if (tree_) {
+  if (tree_)
     tree_->AddObserver(this);
-    live_region_tracker_ = std::make_unique<AXLiveRegionTracker>(tree_);
-  }
 }
 
 AXEventGenerator::~AXEventGenerator() {
@@ -113,15 +110,11 @@
 }
 
 void AXEventGenerator::SetTree(AXTree* new_tree) {
-  if (tree_) {
+  if (tree_)
     tree_->RemoveObserver(this);
-    live_region_tracker_.reset();
-  }
   tree_ = new_tree;
-  if (tree_) {
+  if (tree_)
     tree_->AddObserver(this);
-    live_region_tracker_ = std::make_unique<AXLiveRegionTracker>(tree_);
-  }
 }
 
 void AXEventGenerator::ReleaseTree() {
@@ -482,12 +475,6 @@
 }
 
 void AXEventGenerator::OnNodeWillBeDeleted(AXTree* tree, AXNode* node) {
-  if (node->data().HasStringAttribute(
-          ax::mojom::StringAttribute::kContainerLiveStatus)) {
-    FireLiveRegionEvents(node);
-    live_region_tracker_->OnNodeWillBeDeleted(node);
-  }
-
   DCHECK_EQ(tree_, tree);
   tree_events_.erase(node);
 }
@@ -519,14 +506,6 @@
   }
 
   for (const auto& change : changes) {
-    if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED ||
-         change.type == NODE_REPARENTED || change.type == SUBTREE_REPARENTED)) {
-      if (change.node->data().HasStringAttribute(
-              ax::mojom::StringAttribute::kContainerLiveStatus)) {
-        live_region_tracker_->TrackNode(change.node);
-      }
-    }
-
     if (change.type == SUBTREE_CREATED) {
       AddEvent(change.node, Event::SUBTREE_CREATED);
     } else if (change.type != NODE_CREATED) {
@@ -546,29 +525,23 @@
 }
 
 void AXEventGenerator::FireLiveRegionEvents(AXNode* node) {
-  AXNode* live_root = live_region_tracker_->GetLiveRoot(node);
+  AXNode* live_root = node;
+  while (live_root && !live_root->data().HasStringAttribute(
+                          ax::mojom::StringAttribute::kLiveStatus))
+    live_root = live_root->parent();
 
-  // Note that |live_root| might be nullptr if a live region was just added.
-  if (!live_root)
-    return;
-
-  if (live_root->data().GetBoolAttribute(ax::mojom::BoolAttribute::kBusy))
-    return;
-
-  std::string live_status = live_root->data().GetStringAttribute(
-      ax::mojom::StringAttribute::kLiveStatus);
-  if (live_status != "polite" && live_status != "assertive")
-    return;
-
-  // Fire LIVE_REGION_NODE_CHANGED on each node that changed.
-  if (!node->data()
-           .GetStringAttribute(ax::mojom::StringAttribute::kName)
-           .empty()) {
-    AddEvent(node, Event::LIVE_REGION_NODE_CHANGED);
+  if (live_root &&
+      !live_root->data().GetBoolAttribute(ax::mojom::BoolAttribute::kBusy) &&
+      live_root->data().GetStringAttribute(
+          ax::mojom::StringAttribute::kLiveStatus) != "off") {
+    // Fire LIVE_REGION_NODE_CHANGED on each node that changed.
+    if (!node->data()
+             .GetStringAttribute(ax::mojom::StringAttribute::kName)
+             .empty())
+      AddEvent(node, Event::LIVE_REGION_NODE_CHANGED);
+    // Fire LIVE_REGION_CHANGED on the root of the live region.
+    AddEvent(live_root, Event::LIVE_REGION_CHANGED);
   }
-
-  // Fire LIVE_REGION_CHANGED on the root of the live region.
-  AddEvent(live_root, Event::LIVE_REGION_CHANGED);
 }
 
 void AXEventGenerator::FireActiveDescendantEvents() {
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index aa58667..4016e91 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -6,10 +6,8 @@
 #define UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
 
 #include <map>
-#include <memory>
 #include <ostream>
 #include <set>
-#include <string>
 #include <vector>
 
 #include "ui/accessibility/ax_export.h"
@@ -18,8 +16,6 @@
 
 namespace ui {
 
-class AXLiveRegionTracker;
-
 // Subclass of AXTreeObserver that automatically generates AXEvents to fire
 // based on changes to an accessibility tree.  Every platform
 // tends to want different events, so this class lets each platform
@@ -236,9 +232,6 @@
   // Valid between the call to OnIntAttributeChanged and the call to
   // OnAtomicUpdateFinished. List of nodes whose active descendant changed.
   std::vector<AXNode*> active_descendant_changed_;
-
-  // Helper that tracks live regions.
-  std::unique_ptr<AXLiveRegionTracker> live_region_tracker_;
 };
 
 AX_EXPORT std::ostream& operator<<(std::ostream& os,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc
index fb3d0b4..32a0768 100644
--- a/ui/accessibility/ax_event_generator_unittest.cc
+++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -1370,41 +1370,4 @@
           HasEventAtNode(AXEventGenerator::Event::STATE_CHANGED, 1)));
 }
 
-TEST(AXEventGeneratorTest, LiveRegionNodeRemoved) {
-  AXTreeUpdate initial_state;
-  initial_state.root_id = 1;
-  initial_state.nodes.resize(3);
-  initial_state.nodes[0].id = 1;
-  initial_state.nodes[0].AddStringAttribute(
-      ax::mojom::StringAttribute::kLiveStatus, "polite");
-  initial_state.nodes[0].AddStringAttribute(
-      ax::mojom::StringAttribute::kContainerLiveStatus, "polite");
-  initial_state.nodes[0].child_ids = {2, 3};
-  initial_state.nodes[1].id = 2;
-  initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
-  initial_state.nodes[1].AddStringAttribute(
-      ax::mojom::StringAttribute::kContainerLiveStatus, "polite");
-  initial_state.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
-                                            "Before 1");
-  initial_state.nodes[2].id = 3;
-  initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
-  initial_state.nodes[2].AddStringAttribute(
-      ax::mojom::StringAttribute::kContainerLiveStatus, "polite");
-  initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
-                                            "Before 2");
-  AXTree tree(initial_state);
-
-  AXEventGenerator event_generator(&tree);
-  AXTreeUpdate update = initial_state;
-  update.nodes.resize(1);
-  update.nodes[0].child_ids = {2};
-
-  EXPECT_TRUE(tree.Unserialize(update));
-  EXPECT_THAT(
-      event_generator,
-      UnorderedElementsAre(
-          HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 1),
-          HasEventAtNode(AXEventGenerator::Event::LIVE_REGION_CHANGED, 1)));
-}
-
 }  // namespace ui
diff --git a/ui/accessibility/ax_live_region_tracker.cc b/ui/accessibility/ax_live_region_tracker.cc
deleted file mode 100644
index a2cf7f195..0000000
--- a/ui/accessibility/ax_live_region_tracker.cc
+++ /dev/null
@@ -1,59 +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 "ui/accessibility/ax_live_region_tracker.h"
-
-#include "base/stl_util.h"
-#include "ui/accessibility/ax_node.h"
-#include "ui/accessibility/ax_role_properties.h"
-
-namespace ui {
-
-AXLiveRegionTracker::AXLiveRegionTracker(AXTree* tree) : tree_(tree) {
-  InitializeLiveRegionNodeToRoot(tree_->root(), nullptr);
-}
-
-AXLiveRegionTracker::~AXLiveRegionTracker() {}
-
-void AXLiveRegionTracker::TrackNode(AXNode* node) {
-  LOG(ERROR) << "TrackNode " << node->data().ToString();
-  AXNode* live_root = node;
-  while (live_root && !live_root->HasStringAttribute(
-                          ax::mojom::StringAttribute::kLiveStatus))
-    live_root = live_root->parent();
-  if (live_root) {
-    LOG(ERROR) << "  Live root: " << live_root->data().ToString();
-    live_region_node_to_root_[node] = live_root;
-  } else
-    LOG(ERROR) << "  No live root";
-}
-
-void AXLiveRegionTracker::OnNodeWillBeDeleted(AXNode* node) {
-  LOG(ERROR) << "OnNodeWillBeDeleted " << node->data().ToString();
-  live_region_node_to_root_.erase(node);
-}
-
-AXNode* AXLiveRegionTracker::GetLiveRoot(AXNode* node) {
-  LOG(ERROR) << "GetLiveRoot for " << node->data().ToString();
-  auto iter = live_region_node_to_root_.find(node);
-  if (iter != live_region_node_to_root_.end())
-    return iter->second;
-  return nullptr;
-}
-
-void AXLiveRegionTracker::InitializeLiveRegionNodeToRoot(AXNode* node,
-                                                         AXNode* current_root) {
-  if (!current_root &&
-      node->HasStringAttribute(ax::mojom::StringAttribute::kLiveStatus)) {
-    current_root = node;
-  }
-
-  if (current_root)
-    live_region_node_to_root_[node] = current_root;
-
-  for (size_t i = 0; i < node->children().size(); i++)
-    InitializeLiveRegionNodeToRoot(node->children()[i], current_root);
-}
-
-}  // namespace ui
diff --git a/ui/accessibility/ax_live_region_tracker.h b/ui/accessibility/ax_live_region_tracker.h
deleted file mode 100644
index b530fbab..0000000
--- a/ui/accessibility/ax_live_region_tracker.h
+++ /dev/null
@@ -1,41 +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 UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_
-#define UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "ui/accessibility/ax_tree.h"
-
-namespace ui {
-
-// Class that works with AXEventGenerator to track live regions in
-// an AXTree.
-class AXLiveRegionTracker {
- public:
-  explicit AXLiveRegionTracker(AXTree* tree);
-
-  ~AXLiveRegionTracker();
-
-  void TrackNode(AXNode* node);
-  void OnNodeWillBeDeleted(AXNode* node);
-  AXNode* GetLiveRoot(AXNode* node);
-
- private:
-  void InitializeLiveRegionNodeToRoot(AXNode* node, AXNode* current_root);
-
-  AXTree* tree_;  // Not owned.
-
-  // Map from live region node to its live region root.
-  std::map<AXNode*, AXNode*> live_region_node_to_root_;
-
-  DISALLOW_COPY_AND_ASSIGN(AXLiveRegionTracker);
-};
-
-}  // namespace ui
-
-#endif  // UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_
diff --git a/ui/base/OWNERS b/ui/base/OWNERS
index c46a277..ecd1e72 100644
--- a/ui/base/OWNERS
+++ b/ui/base/OWNERS
@@ -3,5 +3,7 @@
 per-file template_expressions*=michaelpg@chromium.org
 per-file template_expressions*=rbpotter@chromium.org
 
+per-file window_open_disposition*=pkasting@chromium.org
+
 # If you're doing structural changes get a review from one of the ui/OWNERS.
 per-file BUILD.gn=*
diff --git a/ui/base/window_open_disposition.cc b/ui/base/window_open_disposition.cc
index 90d9fbd4..e2e429b 100644
--- a/ui/base/window_open_disposition.cc
+++ b/ui/base/window_open_disposition.cc
@@ -9,11 +9,13 @@
 
 namespace ui {
 
-WindowOpenDisposition DispositionFromClick(bool middle_button,
-                                           bool alt_key,
-                                           bool ctrl_key,
-                                           bool meta_key,
-                                           bool shift_key) {
+WindowOpenDisposition DispositionFromClick(
+    bool middle_button,
+    bool alt_key,
+    bool ctrl_key,
+    bool meta_key,
+    bool shift_key,
+    WindowOpenDisposition disposition_for_current_tab) {
   // MacOS uses meta key (Command key) to spawn new tabs.
 #if defined(OS_MACOSX)
   if (middle_button || meta_key)
@@ -26,16 +28,18 @@
     return WindowOpenDisposition::NEW_WINDOW;
   if (alt_key)
     return WindowOpenDisposition::SAVE_TO_DISK;
-  return WindowOpenDisposition::CURRENT_TAB;
+  return disposition_for_current_tab;
 }
 
-WindowOpenDisposition DispositionFromEventFlags(int event_flags) {
-  return DispositionFromClick(
-      (event_flags & ui::EF_MIDDLE_MOUSE_BUTTON) != 0,
-      (event_flags & ui::EF_ALT_DOWN) != 0,
-      (event_flags & ui::EF_CONTROL_DOWN) != 0,
-      (event_flags & ui::EF_COMMAND_DOWN) != 0,
-      (event_flags & ui::EF_SHIFT_DOWN) != 0);
+WindowOpenDisposition DispositionFromEventFlags(
+    int event_flags,
+    WindowOpenDisposition disposition_for_current_tab) {
+  return DispositionFromClick((event_flags & ui::EF_MIDDLE_MOUSE_BUTTON) != 0,
+                              (event_flags & ui::EF_ALT_DOWN) != 0,
+                              (event_flags & ui::EF_CONTROL_DOWN) != 0,
+                              (event_flags & ui::EF_COMMAND_DOWN) != 0,
+                              (event_flags & ui::EF_SHIFT_DOWN) != 0,
+                              disposition_for_current_tab);
 }
 
 }  // namespace ui
diff --git a/ui/base/window_open_disposition.h b/ui/base/window_open_disposition.h
index 0d8afbd..930024e8 100644
--- a/ui/base/window_open_disposition.h
+++ b/ui/base/window_open_disposition.h
@@ -35,19 +35,26 @@
 
 namespace ui {
 
-// Translates event flags from a click on a link into the user's desired
-// window disposition.  For example, a middle click would mean to open
-// a background tab.
-UI_BASE_EXPORT WindowOpenDisposition DispositionFromClick(bool middle_button,
-                                                          bool alt_key,
-                                                          bool ctrl_key,
-                                                          bool meta_key,
-                                                          bool shift_key);
+// Translates event flags from a click on a link into the user's desired window
+// disposition.  For example, a middle click would mean to open a background
+// tab.  |disposition_for_current_tab| is the disposition to return if the flags
+// suggest opening in the current tab; for example, a caller could set this to
+// NEW_FOREGROUND_TAB to prevent a click from overwriting the current tab by
+// default.
+UI_BASE_EXPORT WindowOpenDisposition
+DispositionFromClick(bool middle_button,
+                     bool alt_key,
+                     bool ctrl_key,
+                     bool meta_key,
+                     bool shift_key,
+                     WindowOpenDisposition disposition_for_current_tab =
+                         WindowOpenDisposition::CURRENT_TAB);
 
-// Translates event flags into what kind of disposition they represents.
-// For example, a middle click would mean to open a background tab.
-// event_flags are the flags as understood by ui::MouseEvent.
-UI_BASE_EXPORT WindowOpenDisposition DispositionFromEventFlags(int event_flags);
+// As with DispositionFromClick(), but using |event_flags| as in ui::MouseEvent.
+UI_BASE_EXPORT WindowOpenDisposition
+DispositionFromEventFlags(int event_flags,
+                          WindowOpenDisposition disposition_for_current_tab =
+                              WindowOpenDisposition::CURRENT_TAB);
 
 }  // namespace ui
 
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn
index c716bcb2..5f86e6d 100644
--- a/ui/base/x/BUILD.gn
+++ b/ui/base/x/BUILD.gn
@@ -64,6 +64,7 @@
   deps = [
     "//base",
     "//base:i18n",
+    "//net",
     "//skia",
     "//ui/base:hit_test",
     "//ui/base/clipboard:clipboard_types",
diff --git a/ui/base/x/x11_shm_image_pool_base.cc b/ui/base/x/x11_shm_image_pool_base.cc
index cabf6e0..9baf516 100644
--- a/ui/base/x/x11_shm_image_pool_base.cc
+++ b/ui/base/x/x11_shm_image_pool_base.cc
@@ -18,6 +18,7 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "net/base/url_util.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/gfx/geometry/rect.h"
@@ -54,8 +55,35 @@
   return max_size;
 }
 
+bool IsRemoteHost(const std::string& name) {
+  if (name.empty())
+    return false;
+
+  char hostname[256];
+  if (!gethostname(hostname, sizeof(hostname)) && name == hostname)
+    return false;
+
+  return !net::HostStringIsLocalhost(name);
+}
+
+bool ShouldUseMitShm(XDisplay* display) {
+  // MIT-SHM may be available on remote connetions, but it will be unusable.  Do
+  // a best-effort check to see if the host is remote to disable the SHM
+  // codepath.  It may be possible in contrived cases for there to be a
+  // false-positive, but in that case we'll just fallback to the non-SHM
+  // codepath.
+  char* display_string = DisplayString(display);
+  char* host = nullptr;
+  int display_id = 0;
+  int screen = 0;
+  if (xcb_parse_display(display_string, &host, &display_id, &screen)) {
+    std::string name = host;
+    free(host);
+    if (IsRemoteHost(name))
+      return false;
+  }
+
 #if !defined(OS_CHROMEOS)
-bool ShouldUseMitShm() {
   std::unique_ptr<base::Environment> env = base::Environment::Create();
 
   // Used by QT.
@@ -73,10 +101,10 @@
   // Used by GTK.
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoXshm))
     return false;
+#endif
 
   return true;
 }
-#endif
 
 }  // namespace
 
@@ -119,10 +147,8 @@
   if (!event_task_runner_)
     return false;
 
-#if !defined(OS_CHROMEOS)
-  if (!ShouldUseMitShm())
+  if (!ShouldUseMitShm(display_))
     return false;
-#endif
 
   if (!ui::QueryShmSupport())
     return false;
diff --git a/ui/events/blink/compositor_thread_event_queue.cc b/ui/events/blink/compositor_thread_event_queue.cc
index 8d4e064..f9c2b46 100644
--- a/ui/events/blink/compositor_thread_event_queue.cc
+++ b/ui/events/blink/compositor_thread_event_queue.cc
@@ -76,12 +76,12 @@
 
   std::unique_ptr<EventWithCallback> scroll_event =
       std::make_unique<EventWithCallback>(
-          coalesced_events.first.Clone(), oldest_latency,
+          WebInputEventTraits::Clone(coalesced_events.first), oldest_latency,
           oldest_creation_timestamp, timestamp_now, nullptr);
 
   std::unique_ptr<EventWithCallback> pinch_event =
       std::make_unique<EventWithCallback>(
-          coalesced_events.second.Clone(), oldest_latency,
+          WebInputEventTraits::Clone(coalesced_events.second), oldest_latency,
           oldest_creation_timestamp, timestamp_now,
           std::move(combined_original_events));
 
diff --git a/ui/events/blink/event_with_callback.cc b/ui/events/blink/event_with_callback.cc
index c3c685d..cbed0013 100644
--- a/ui/events/blink/event_with_callback.cc
+++ b/ui/events/blink/event_with_callback.cc
@@ -19,7 +19,7 @@
     const LatencyInfo& latency,
     base::TimeTicks timestamp_now,
     InputHandlerProxy::EventDispositionCallback callback)
-    : event_(event->Clone()),
+    : event_(WebInputEventTraits::Clone(*event)),
       latency_(latency),
       creation_timestamp_(timestamp_now),
       last_coalesced_timestamp_(timestamp_now) {
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 44408325..ec7b9e8 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -83,6 +83,8 @@
       NOTREACHED();
       break;
   }
+  scroll_state_data.is_direct_manipulation =
+      event.SourceDevice() == blink::WebGestureDevice::kTouchscreen;
   return cc::ScrollState(scroll_state_data);
 }
 
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index 9b2b867f..cf89aaa4 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -94,7 +94,7 @@
     gesture.data.pinch_update.scale = delta_y_or_scale;
     gesture.SetPositionInWidget(gfx::PointF(x, y));
   }
-  return gesture.Clone();
+  return WebInputEventTraits::Clone(gesture);
 }
 
 class MockInputHandler : public cc::InputHandler {
@@ -2640,14 +2640,14 @@
     WebGestureEvent gesture(WebInputEvent::kGestureScrollBegin,
                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
                             blink::WebGestureDevice::kTouchscreen);
-    HandleGesture(gesture.Clone());
+    HandleGesture(WebInputEventTraits::Clone(gesture));
   }
 
   void HandleScrollEnd() {
     WebGestureEvent gesture(WebInputEvent::kGestureScrollEnd,
                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
                             blink::WebGestureDevice::kTouchscreen);
-    HandleGesture(gesture.Clone());
+    HandleGesture(WebInputEventTraits::Clone(gesture));
   }
 
   void HandleScrollUpdate(bool is_momentum) {
@@ -2659,7 +2659,7 @@
       gesture.data.scroll_update.inertial_phase =
           blink::WebGestureEvent::InertialPhaseState::kMomentum;
     }
-    HandleGesture(gesture.Clone());
+    HandleGesture(WebInputEventTraits::Clone(gesture));
   }
 
   void AdvanceClock(uint32_t milliseconds) {
diff --git a/ui/events/blink/scroll_predictor_unittest.cc b/ui/events/blink/scroll_predictor_unittest.cc
index e8409d2..cbf1b883 100644
--- a/ui/events/blink/scroll_predictor_unittest.cc
+++ b/ui/events/blink/scroll_predictor_unittest.cc
@@ -58,10 +58,10 @@
     gesture.data.scroll_update.delta_y = delta_y;
     gesture.data.scroll_update.inertial_phase = phase;
 
-    original_events_.emplace_back(gesture.Clone(), LatencyInfo(),
-                                  base::NullCallback());
+    original_events_.emplace_back(WebInputEventTraits::Clone(gesture),
+                                  LatencyInfo(), base::NullCallback());
 
-    return gesture.Clone();
+    return WebInputEventTraits::Clone(gesture);
   }
 
   void CoalesceWith(const WebScopedInputEvent& new_event,
@@ -90,7 +90,7 @@
         WebInputEvent::GetStaticTimeStampForTests() +
             base::TimeDelta::FromMillisecondsD(time_delta_in_milliseconds));
 
-    event = event_with_callback->event().Clone();
+    event = WebInputEventTraits::Clone(event_with_callback->event());
   }
 
   std::unique_ptr<ui::InputPredictor::InputData> PredictionAvailable(
@@ -203,7 +203,7 @@
                               WebInputEvent::kNoModifiers,
                               WebInputEvent::GetStaticTimeStampForTests(),
                               blink::WebGestureDevice::kTouchscreen);
-  WebScopedInputEvent event = gesture_end.Clone();
+  WebScopedInputEvent event = WebInputEventTraits::Clone(gesture_end);
   HandleResampleScrollEvents(event);
   EXPECT_FALSE(GetResamplingState());
 }
diff --git a/ui/events/blink/web_input_event_traits.cc b/ui/events/blink/web_input_event_traits.cc
index 19bd615..9734e1d 100644
--- a/ui/events/blink/web_input_event_traits.cc
+++ b/ui/events/blink/web_input_event_traits.cc
@@ -105,6 +105,17 @@
       event.rotation_angle, event.tilt_x, event.tilt_y);
 }
 
+struct WebInputEventDelete {
+  template <class EventType>
+  bool Execute(WebInputEvent* event, void*) const {
+    if (!event)
+      return false;
+    DCHECK_EQ(sizeof(EventType), event->size());
+    delete static_cast<EventType*>(event);
+    return true;
+  }
+};
+
 struct WebInputEventToString {
   template <class EventType>
   bool Execute(const WebInputEvent& event, std::string* result) const {
@@ -118,6 +129,17 @@
   }
 };
 
+struct WebInputEventClone {
+  template <class EventType>
+  bool Execute(const WebInputEvent& event,
+               WebScopedInputEvent* scoped_event) const {
+    DCHECK_EQ(sizeof(EventType), event.size());
+    *scoped_event = WebScopedInputEvent(
+        new EventType(static_cast<const EventType&>(event)));
+    return true;
+  }
+};
+
 template <typename Operator, typename ArgIn, typename ArgOut>
 bool Apply(Operator op,
            WebInputEvent::Type type,
@@ -142,12 +164,25 @@
 
 }  // namespace
 
+void WebInputEventDeleter::operator()(WebInputEvent* event) const {
+  if (!event)
+    return;
+  void* temp = nullptr;
+  Apply(WebInputEventDelete(), event->GetType(), event, temp);
+}
+
 std::string WebInputEventTraits::ToString(const WebInputEvent& event) {
   std::string result;
   Apply(WebInputEventToString(), event.GetType(), event, &result);
   return result;
 }
 
+WebScopedInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
+  WebScopedInputEvent scoped_event;
+  Apply(WebInputEventClone(), event.GetType(), event, &scoped_event);
+  return scoped_event;
+}
+
 bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
   switch (event.GetType()) {
     case WebInputEvent::kContextMenu:
diff --git a/ui/events/blink/web_input_event_traits.h b/ui/events/blink/web_input_event_traits.h
index 10f60ba..19f9db8b 100644
--- a/ui/events/blink/web_input_event_traits.h
+++ b/ui/events/blink/web_input_event_traits.h
@@ -14,12 +14,18 @@
 
 namespace ui {
 
-using WebScopedInputEvent = std::unique_ptr<blink::WebInputEvent>;
+struct WebInputEventDeleter {
+  void operator()(blink::WebInputEvent*) const;
+};
+
+using WebScopedInputEvent =
+    std::unique_ptr<blink::WebInputEvent, WebInputEventDeleter>;
 
 // Utility class for performing operations on and with WebInputEvents.
 class WebInputEventTraits {
  public:
   static std::string ToString(const blink::WebInputEvent& event);
+  static WebScopedInputEvent Clone(const blink::WebInputEvent& event);
   static bool ShouldBlockEventStream(const blink::WebInputEvent& event);
 
   // Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
diff --git a/ui/ozone/demo/skia/skia_gl_renderer.cc b/ui/ozone/demo/skia/skia_gl_renderer.cc
index 11e39bcf..a4ed2416 100644
--- a/ui/ozone/demo/skia/skia_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_gl_renderer.cc
@@ -30,12 +30,6 @@
 
 namespace {
 
-const GrGLInterface* GrGLCreateNativeInterface() {
-  return GrGLAssembleInterface(nullptr, [](void* ctx, const char name[]) {
-    return gl::GetGLProcAddress(name);
-  });
-}
-
 const char kUseDDL[] = "use-ddl";
 
 }  // namespace
@@ -71,8 +65,9 @@
     return false;
   }
 
-  auto native_interface =
-      sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
+  sk_sp<const GrGLInterface> native_interface = GrGLMakeAssembledInterface(
+      nullptr,
+      [](void* ctx, const char name[]) { return gl::GetGLProcAddress(name); });
   DCHECK(native_interface);
   GrContextOptions options;
   // TODO(csmartdalton): enable internal multisampling after the related Skia
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index ce49bdc..db72e2d 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -899,7 +899,9 @@
 }
 
 // Tests the shadow type given in InitParams.
-TEST_F(BridgedNativeWidgetInitTest, ShadowType) {
+// Disabled because shadows are disabled on the bots - see
+// https://crbug.com/899286.
+TEST_F(BridgedNativeWidgetInitTest, DISABLED_ShadowType) {
   // Verify Widget::InitParam defaults and arguments added from SetUp().
   EXPECT_EQ(Widget::InitParams::TYPE_WINDOW_FRAMELESS, type_);
   EXPECT_EQ(Widget::InitParams::WindowOpacity::kOpaque, opacity_);
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn
index 2efffba..4289652 100644
--- a/weblayer/shell/android/BUILD.gn
+++ b/weblayer/shell/android/BUILD.gn
@@ -158,8 +158,8 @@
   deps = [
     ":weblayer_support_manifest",
     "//android_webview:locale_pak_assets",
-    "//android_webview:monochrome_webview_assets",
     "//android_webview:pak_file_assets",
+    "//android_webview:weblayer_webview_assets",
     "//base:base_java",
     "//weblayer:locale_pak_assets",
     "//weblayer/browser/java",