diff --git a/DEPS b/DEPS
index 143f66b..b6334c3 100644
--- a/DEPS
+++ b/DEPS
@@ -200,11 +200,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': 'bc75ebb1afc47a03574c02f1ff470949f1cf5b6d',
+  'skia_revision': '7bce89d89d4bb26068689a8ab48e5a5767be0a7c',
   # 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': '3b5297a49d17ce34f41077573706a37c05d69745',
+  'v8_revision': '0652fd726a951b9275547e541b83703cf77c35b0',
   # 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.
@@ -212,7 +212,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '9041ca0c340728abbb36fd7033a491e9d340e823',
+  'angle_revision': '130597e10299d995f9d9eed6ec17e6d7d1f8f2be',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -220,7 +220,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'ab436aebc566b8f86d8cd93037bba2d2c93e0edf',
+  'pdfium_revision': 'd6c1c090774fc96db14f0f71a8b9f4ada85f2485',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -267,7 +267,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': 'a629d81faa7aca80572b7a45df4589d952509664',
+  'catapult_revision': 'ae003f552e4e16247758303d671076690c405c45',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -327,7 +327,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '90bac683b40fc0d051aca35cd455ef6baa77ddf2',
+  'dawn_revision': '70102b71900bd6938eaa65c92da700aa549efc6e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -543,7 +543,7 @@
   },
 
     'src/ios/third_party/edo/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'e8a984232246078667bfb2699494bc0fc0b363fb',
+      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '91c532d921e1f37f7e0f213c534df16df6061ec1',
       'condition': 'checkout_ios',
   },
 
@@ -919,7 +919,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4c5dd5d863c416ee7a20d38d94c612eca1bd34c8',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8820ab859bea6cf5ed2751c9373098a688ad1a03',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1274,7 +1274,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '185795f02ceb4300e1caef49b5b7052c8d453dc9',
+    Var('chromium_git') + '/openscreen' + '@' + '759af7f402131028b48a107ca33d4b1ee2fdaeb6',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '97cfe495bb7a3853266b646d1c79e169387f9c7a',
@@ -1369,7 +1369,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'xP-64hTow-Hi_OEgw5l-GAguP8htsWKyhoX-a9Fj9KcC'
+              'version': 'b5ckZyVJ3XwwvnxV2J_ybKfLyiHfOj81r9Llym22_UsC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1551,7 +1551,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3f77eb468fc4a9a7f5e2751d3d3cbbda38e95082',
+    Var('webrtc_git') + '/src.git' + '@' + 'bafeede2b523627a2c36b4e5b508a8c0b41acea0',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1623,7 +1623,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f66650677465f8979e192ac5df1d4c87c1bcafcc',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@724b0bf4449d7f361cab700772453c2cd28153b9',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 5dd6bbb..2ae8b82d 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -443,6 +443,7 @@
     "java/src/org/chromium/android_webview/AwDebug.java",
     "java/src/org/chromium/android_webview/AwDevToolsServer.java",
     "java/src/org/chromium/android_webview/AwDisplayCutoutController.java",
+    "java/src/org/chromium/android_webview/AwDisplayModeController.java",
     "java/src/org/chromium/android_webview/AwFeatureList.java",
     "java/src/org/chromium/android_webview/AwFormDatabase.java",
     "java/src/org/chromium/android_webview/AwGeolocationPermissions.java",
@@ -551,6 +552,7 @@
     "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/blink/public:blink_headers_java",
+    "//third_party/blink/public/mojom:mojom_platform_java",
     "//ui/android:ui_no_recycler_view_java",
     "//url:gurl_java",
   ]
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.cc b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
index d2525ac629..44622b3 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.cc
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
@@ -215,6 +215,13 @@
   return !!globals_;
 }
 
+bool AwVulkanContextProvider::InitializeGrContext(
+    const GrContextOptions& context_options) {
+  // GrContext is created in Globals, so nothing to do here besides DCHECK.
+  DCHECK(globals_);
+  return globals_->gr_context.get() != nullptr;
+}
+
 void AwVulkanContextProvider::SecondaryCBDrawBegin(
     sk_sp<GrVkSecondaryCBDrawContext> draw_context) {
   DCHECK(draw_context);
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.h b/android_webview/browser/gfx/aw_vulkan_context_provider.h
index d8c719bc..39e19b8 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.h
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.h
@@ -48,6 +48,7 @@
       AwDrawFn_InitVkParams* params);
 
   // viz::VulkanContextProvider implementation:
+  bool InitializeGrContext(const GrContextOptions& context_options) override;
   gpu::VulkanImplementation* GetVulkanImplementation() override;
   gpu::VulkanDeviceQueue* GetDeviceQueue() override;
   GrDirectContext* GetGrContext() override;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index f26f5c9..9fdb641 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -496,6 +496,8 @@
 
     private ContentCaptureConsumer mContentCaptureConsumer;
 
+    private final AwDisplayModeController mDisplayModeController;
+
     private static class WebContentsInternalsHolder implements WebContents.InternalsHolder {
         private final WeakReference<AwContents> mAwContentsRef;
 
@@ -944,6 +946,20 @@
             AwSettings settings, DependencyFactory dependencyFactory) {
         assert browserContext != null;
         try (ScopedSysTraceEvent e1 = ScopedSysTraceEvent.scoped("AwContents.constructor")) {
+            mDisplayModeController =
+                    new AwDisplayModeController(new AwDisplayModeController.Delegate() {
+                        @Override
+                        public int getDisplayWidth() {
+                            WindowAndroid windowAndroid = mWindowAndroid.getWindowAndroid();
+                            return windowAndroid.getDisplay().getDisplayWidth();
+                        }
+
+                        @Override
+                        public int getDisplayHeight() {
+                            WindowAndroid windowAndroid = mWindowAndroid.getWindowAndroid();
+                            return windowAndroid.getDisplay().getDisplayHeight();
+                        }
+                    }, containerView);
             mRendererPriority = RendererPriority.HIGH;
             mSettings = settings;
             updateDefaultLocale();
@@ -1188,6 +1204,7 @@
         awViewMethodsImpl.onFocusChanged(mContainerView.hasFocus(), 0, null);
         mContainerView.requestLayout();
         if (mAutofillProvider != null) mAutofillProvider.onContainerViewChanged(mContainerView);
+        mDisplayModeController.setCurrentContainerView(mContainerView);
     }
 
     // This class destroys the WindowAndroid when after it is gc-ed.
@@ -3361,6 +3378,10 @@
         return AwContentsJni.get().getRenderProcess(mNativeAwContents, AwContents.this);
     }
 
+    public int getDisplayMode() {
+        return mDisplayModeController.getDisplayMode();
+    }
+
     //--------------------------------------------------------------------------------------------
     //  Methods called from native via JNI
     //--------------------------------------------------------------------------------------------
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java b/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java
new file mode 100644
index 0000000..c9f1459
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java
@@ -0,0 +1,136 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import android.annotation.SuppressLint;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.view.View;
+
+import org.chromium.base.Log;
+import org.chromium.blink.mojom.DisplayMode;
+
+/**
+ * Display mode controller for WebView.
+ *
+ * Display mode will be used for display cutout controller's internal implementation since we only
+ * apply display cutout to fullscreen mode. Also, display mode will be reported as CSS property.
+ */
+public class AwDisplayModeController {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "DisplayMode";
+
+    /**
+     * This is a delegate that the embedder needs to implement.
+     */
+    public interface Delegate {
+        /** @return The display width. */
+        int getDisplayWidth();
+        /** @return The display height. */
+        int getDisplayHeight();
+    }
+
+    private Delegate mDelegate;
+    private View mContainerView;
+
+    // Reuse these structures to minimize memory impact.
+    private static final int[] sCachedLocationOnScreen = {0, 0};
+    private static final Rect sCachedViewRect = new Rect();
+    private static final Rect sCachedWindowRect = new Rect();
+    private static final Rect sCachedDisplayRect = new Rect();
+    private static final Matrix sCachedMatrix = new Matrix();
+
+    /**
+     * Constructor for AwDisplayModeController.
+     *
+     * @param delegate The delegate.
+     * @param containerView The container view (WebView).
+     */
+    public AwDisplayModeController(Delegate delegate, View containerView) {
+        mContainerView = containerView;
+        mDelegate = delegate;
+    }
+
+    public int getDisplayMode() {
+        // We currently do not support other display modes.
+        return isDisplayInFullscreen() ? DisplayMode.FULLSCREEN : DisplayMode.BROWSER;
+    }
+
+    private boolean isDisplayInFullscreen() {
+        getViewRectOnScreen(mContainerView, sCachedViewRect);
+        getViewRectOnScreen(mContainerView.getRootView(), sCachedWindowRect);
+
+        // Get display coordinates.
+        int displayWidth = mDelegate.getDisplayWidth();
+        int displayHeight = mDelegate.getDisplayHeight();
+        sCachedDisplayRect.set(0, 0, displayWidth, displayHeight);
+
+        if (DEBUG) {
+            Log.i(TAG,
+                    "isDisplayInFullscreen. view rect: " + sCachedViewRect + ", display rect: "
+                            + sCachedDisplayRect + ", window rect: " + sCachedWindowRect);
+        }
+
+        // Display is in fullscreen only when webview is occupying the entire window and display.
+        // Checking the window rect is more complicated and therefore not doing it for now, but
+        // there can still be cases where the window is a bit off.
+        if (!sCachedViewRect.equals(sCachedDisplayRect)) {
+            if (DEBUG) {
+                Log.i(TAG, "WebView is not occupying the entire screen.");
+            }
+            return false;
+        } else if (!sCachedViewRect.equals(sCachedWindowRect)) {
+            if (DEBUG) {
+                Log.i(TAG, "WebView is not occupying the entire window.");
+            }
+            return false;
+        } else if (hasTransform()) {
+            if (DEBUG) {
+                Log.i(TAG, "WebView is rotated or scaled.");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private static void getViewRectOnScreen(View view, Rect rect) {
+        if (view == null) {
+            rect.set(0, 0, 0, 0);
+            return;
+        }
+        view.getLocationOnScreen(sCachedLocationOnScreen);
+        int width = view.getMeasuredWidth();
+        int height = view.getMeasuredHeight();
+
+        rect.set(sCachedLocationOnScreen[0], sCachedLocationOnScreen[1],
+                sCachedLocationOnScreen[0] + width, sCachedLocationOnScreen[1] + height);
+    }
+
+    @SuppressLint("NewApi") // need this exception since we will try using Q API in P
+    private boolean hasTransform() {
+        sCachedMatrix.reset(); // set to identity
+        // Check if a view coordinates transforms to screen coordinates that is not an identity
+        // matrix, which means that view is rotated or scaled in regards to the screen.
+        // This API got hidden from L, and readded in API 29 (Q). It seems that we can call this
+        // on P most of the time, but adding try-catch just in case.
+        try {
+            mContainerView.transformMatrixToGlobal(sCachedMatrix);
+        } catch (Throwable e) {
+            Log.w(TAG, "Error checking transform for display mode: ", e);
+            return true;
+        }
+        return !sCachedMatrix.isIdentity();
+    }
+
+    /**
+     * Set the current container view.
+     *
+     * @param containerView The current container view.
+     */
+    public void setCurrentContainerView(View containerView) {
+        if (DEBUG) Log.i(TAG, "setCurrentContainerView: " + containerView);
+        mContainerView = containerView;
+    }
+}
\ No newline at end of file
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
index 9eac68a..2650126 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -266,6 +266,11 @@
     }
 
     @Override
+    public int getDisplayMode() {
+        return mAwContents.getDisplayMode();
+    }
+
+    @Override
     public void loadingStateChanged() {
         mContentsClient.updateTitle(mAwContents.getTitle(), false);
     }
diff --git a/android_webview/junit/src/org/chromium/android_webview/robolectric/AwDisplayModeControllerTest.java b/android_webview/junit/src/org/chromium/android_webview/robolectric/AwDisplayModeControllerTest.java
new file mode 100644
index 0000000..bd3e2e9
--- /dev/null
+++ b/android_webview/junit/src/org/chromium/android_webview/robolectric/AwDisplayModeControllerTest.java
@@ -0,0 +1,213 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview.robolectric;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLog;
+
+import org.chromium.android_webview.AwDisplayModeController;
+import org.chromium.base.Log;
+import org.chromium.base.test.util.Feature;
+import org.chromium.blink.mojom.DisplayMode;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * JUnit tests for AwDisplayModeController.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class AwDisplayModeControllerTest {
+    private static final String TAG = "DisplayModeTest";
+    private static final boolean DEBUG = false;
+
+    private InOrder mInOrder;
+    private Context mContext;
+
+    @Mock
+    private AwDisplayModeController.Delegate mDelegate;
+    @Mock
+    private View mView;
+    @Mock
+    private View mAnotherView;
+
+    @Mock
+    private ViewGroup mParentView;
+    @Mock
+    private ViewGroup mRootView;
+
+    private View.OnApplyWindowInsetsListener mListener;
+    private int[] mLocationOnScreen = {0, 0};
+    private int mViewWidth;
+    private int mViewHeight;
+
+    private Matrix mGlobalTransformMatrix;
+
+    private float mDipScale;
+    private int mDisplayWidth;
+    private int mDisplayHeight;
+
+    private AwDisplayModeController mController;
+
+    public AwDisplayModeControllerTest() {
+        if (DEBUG) ShadowLog.stream = System.out; // allows logging
+    }
+
+    @Before
+    public void setUp() {
+        if (DEBUG) Log.i(TAG, "setUp");
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        // Set up default values.
+        mViewWidth = 300;
+        mViewHeight = 400;
+        mDisplayWidth = 300;
+        mDisplayHeight = 400;
+        mGlobalTransformMatrix = new Matrix(); // identity matrix
+
+        // Set up the view.
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                int[] loc = (int[]) (invocation.getArguments()[0]);
+                loc[0] = mLocationOnScreen[0];
+                loc[1] = mLocationOnScreen[1];
+                return null;
+            }
+        })
+                .when(mView)
+                .getLocationOnScreen(any(int[].class));
+
+        when(mView.getMeasuredWidth()).thenReturn(mViewWidth);
+        when(mView.getMeasuredHeight()).thenReturn(mViewHeight);
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Matrix matrix = (Matrix) (invocation.getArguments()[0]);
+                matrix.set(mGlobalTransformMatrix);
+                return null;
+            }
+        })
+                .when(mView)
+                .transformMatrixToGlobal(any(Matrix.class));
+
+        // Set up the root view.
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                int[] loc = (int[]) (invocation.getArguments()[0]);
+                loc[0] = mLocationOnScreen[0];
+                loc[1] = mLocationOnScreen[1];
+                return null;
+            }
+        })
+                .when(mRootView)
+                .getLocationOnScreen(any(int[].class));
+        when(mRootView.getMeasuredWidth()).thenReturn(mViewWidth);
+        when(mRootView.getMeasuredHeight()).thenReturn(mViewHeight);
+        when(mView.getRootView()).thenReturn(mRootView);
+
+        // Set up the delegate.
+        when(mDelegate.getDisplayWidth()).thenReturn(mDisplayWidth);
+        when(mDelegate.getDisplayHeight()).thenReturn(mDisplayHeight);
+
+        mInOrder = inOrder(mDelegate, mView, mAnotherView);
+
+        mController = new AwDisplayModeController(mDelegate, mView);
+
+        mInOrder.verifyNoMoreInteractions();
+    }
+
+    @After
+    public void tearDown() {
+        if (DEBUG) Log.i(TAG, "tearDown");
+        mInOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testFullscreen() {
+        Assert.assertEquals(DisplayMode.FULLSCREEN, mController.getDisplayMode());
+
+        mInOrder.verify(mView).getLocationOnScreen(any(int[].class));
+        mInOrder.verify(mView).getMeasuredWidth();
+        mInOrder.verify(mView).getMeasuredHeight();
+        mInOrder.verify(mDelegate).getDisplayWidth();
+        mInOrder.verify(mDelegate).getDisplayHeight();
+        mInOrder.verify(mView).transformMatrixToGlobal(any(Matrix.class));
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testNotFullscreen_NotOccupyingFullDisplay() {
+        // View is not occupying the entire display, so no insets applied.
+        when(mView.getMeasuredHeight()).thenReturn(mDisplayHeight / 2);
+
+        Assert.assertEquals(DisplayMode.BROWSER, mController.getDisplayMode());
+
+        mInOrder.verify(mView).getLocationOnScreen(any(int[].class));
+        mInOrder.verify(mView).getMeasuredWidth();
+        mInOrder.verify(mView).getMeasuredHeight();
+        mInOrder.verify(mDelegate).getDisplayWidth();
+        mInOrder.verify(mDelegate).getDisplayHeight();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testNotFullscreen_NotOccupyingFullWindow() {
+        // View is not occupying the entire window, so no insets applied.
+        when(mRootView.getMeasuredHeight()).thenReturn(mViewHeight / 2);
+
+        Assert.assertEquals(DisplayMode.BROWSER, mController.getDisplayMode());
+
+        mInOrder.verify(mView).getLocationOnScreen(any(int[].class));
+        mInOrder.verify(mView).getMeasuredWidth();
+        mInOrder.verify(mView).getMeasuredHeight();
+        mInOrder.verify(mDelegate).getDisplayWidth();
+        mInOrder.verify(mDelegate).getDisplayHeight();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testNotFullscreen_ParentLayoutRotated() {
+        mGlobalTransformMatrix.postRotate(30.0f);
+
+        Assert.assertEquals(DisplayMode.BROWSER, mController.getDisplayMode());
+
+        mInOrder.verify(mView).getLocationOnScreen(any(int[].class));
+        mInOrder.verify(mView).getMeasuredWidth();
+        mInOrder.verify(mView).getMeasuredHeight();
+        mInOrder.verify(mDelegate).getDisplayWidth();
+        mInOrder.verify(mDelegate).getDisplayHeight();
+        mInOrder.verify(mView).transformMatrixToGlobal(any(Matrix.class));
+    }
+}
\ No newline at end of file
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 55ca95ff..f7af2972 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -498,6 +498,7 @@
 junit_binary("android_webview_junit_tests") {
   sources = [
     "../junit/src/org/chromium/android_webview/robolectric/AwDisplayCutoutControllerTest.java",
+    "../junit/src/org/chromium/android_webview/robolectric/AwDisplayModeControllerTest.java",
     "../junit/src/org/chromium/android_webview/robolectric/AwLayoutSizerTest.java",
     "../junit/src/org/chromium/android_webview/robolectric/AwScrollOffsetManagerTest.java",
     "../junit/src/org/chromium/android_webview/robolectric/FindAddressTest.java",
@@ -518,6 +519,7 @@
     "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/blink/public/mojom:mojom_platform_java",
   ]
 
   package_name = "org.chromium.android_webview.robolectric"
diff --git a/android_webview/ui/grit_resources_allowlist.txt b/android_webview/ui/grit_resources_allowlist.txt
index 672f1d4..0451867 100644
--- a/android_webview/ui/grit_resources_allowlist.txt
+++ b/android_webview/ui/grit_resources_allowlist.txt
@@ -8,8 +8,8 @@
 IDR_SAFE_BROWSING_CSS
 IDR_SAFE_BROWSING_JS
 IDR_SAFE_BROWSING_HTML
-IDR_WEBUI_JS_CR_JS
-IDR_WEBUI_JS_ASSERT_JS
-IDR_WEBUI_JS_UTIL_JS
-IDR_WEBUI_JS_PROMISE_RESOLVER_JS
-IDR_MOJO_MOJO_BINDINGS_LITE_JS
+IDR_WEBUI_JS_CR_M_JS
+IDR_WEBUI_JS_ASSERT_M_JS
+IDR_WEBUI_JS_UTIL_M_JS
+IDR_WEBUI_JS_PROMISE_RESOLVER_M_JS
+IDR_MOJO_BINDINGS_JS
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc
index 1a4618d..51b9fef 100644
--- a/ash/capture_mode/capture_mode_session.cc
+++ b/ash/capture_mode/capture_mode_session.cc
@@ -128,6 +128,18 @@
 // widget will shrink down from 120% -> 100% and fade in.
 constexpr float kLabelScaleUpOnCountdown = 1.2;
 
+// Animation parameters for capture bar overlapping the user capture region.
+// The default animation duration for opacity changes to the capture bar.
+constexpr base::TimeDelta kCaptureBarOpacityChangeDuration =
+    base::TimeDelta::FromMilliseconds(100);
+// The animation duration for showing the capture bar on mouse/touch release.
+constexpr base::TimeDelta kCaptureBarOnReleaseOpacityChangeDuration =
+    base::TimeDelta::FromMilliseconds(167);
+// When the capture bar and user capture region overlap and the mouse is not
+// hovering over the capture bar, drop the opacity to this value to make the
+// region easier to see.
+constexpr float kCaptureBarOverlapOpacity = 0.1;
+
 // Mouse cursor warping is disabled when the capture source is a custom region.
 // Sets the mouse warp status to |enable| and return the original value.
 bool SetMouseWarpEnabled(bool enable) {
@@ -449,15 +461,15 @@
   label_view->StartCountDown(std::move(countdown_finished_callback));
   UpdateCaptureLabelWidgetBounds(/*animate=*/true);
 
-  // Fade out toolbar.
-  ui::Layer* toolbar_layer = capture_mode_bar_widget_->GetLayer();
-  ui::ScopedLayerAnimationSettings toolbar_settings(
-      toolbar_layer->GetAnimator());
-  toolbar_settings.SetTransitionDuration(kCaptureBarFadeOutDuration);
-  toolbar_settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
-  toolbar_settings.SetPreemptionStrategy(
+  // Fade out the capture bar.
+  ui::Layer* capture_bar_layer = capture_mode_bar_widget_->GetLayer();
+  ui::ScopedLayerAnimationSettings capture_bar_settings(
+      capture_bar_layer->GetAnimator());
+  capture_bar_settings.SetTransitionDuration(kCaptureBarFadeOutDuration);
+  capture_bar_settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
+  capture_bar_settings.SetPreemptionStrategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-  toolbar_layer->SetOpacity(0.f);
+  capture_bar_layer->SetOpacity(0.f);
 
   // Fade out the shield if it's recording fullscreen.
   if (controller_->source() == CaptureModeSource::kFullscreen) {
@@ -707,6 +719,10 @@
     event->StopPropagation();
   }
 
+  const bool region_intersects_capture_bar =
+      capture_mode_bar_widget_->GetWindowBoundsInScreen().Intersects(
+          controller_->user_capture_region());
+
   switch (event->type()) {
     case ui::ET_MOUSE_PRESSED:
     case ui::ET_TOUCH_PRESSED:
@@ -724,7 +740,15 @@
         SetMouseWarpEnabled(*old_mouse_warp_status_);
       old_mouse_warp_status_.reset();
 
-      OnLocatedEventReleased(location, is_event_on_capture_bar);
+      OnLocatedEventReleased(location, is_event_on_capture_bar,
+                             region_intersects_capture_bar);
+      break;
+    case ui::ET_MOUSE_MOVED:
+      if (region_intersects_capture_bar) {
+        UpdateCaptureBarWidgetOpacity(
+            is_event_on_capture_bar ? 1.f : kCaptureBarOverlapOpacity,
+            /*on_release=*/false);
+      }
       break;
     default:
       break;
@@ -776,6 +800,9 @@
   is_drag_in_progress_ = true;
   Shell::Get()->UpdateCursorCompositingEnabled();
 
+  if (!is_event_on_capture_bar)
+    UpdateCaptureBarWidgetOpacity(0.f, /*on_release=*/false);
+
   if (is_selecting_region_)
     return;
 
@@ -866,13 +893,21 @@
 
 void CaptureModeSession::OnLocatedEventReleased(
     const gfx::Point& location_in_root,
-    bool is_event_on_capture_bar) {
+    bool is_event_on_capture_bar,
+    bool region_intersects_capture_bar) {
   fine_tune_position_ = FineTunePosition::kNone;
   anchor_points_.clear();
 
   is_drag_in_progress_ = false;
   Shell::Get()->UpdateCursorCompositingEnabled();
 
+  // TODO(richui): update this for tablet mode.
+  UpdateCaptureBarWidgetOpacity(
+      region_intersects_capture_bar && !is_event_on_capture_bar
+          ? kCaptureBarOverlapOpacity
+          : 1.f,
+      /*on_release=*/true);
+
   // Do a repaint to show the affordance circles.
   gfx::Rect damage_region = controller_->user_capture_region();
   damage_region.Inset(gfx::Insets(-kDamageInsetDp));
@@ -1302,4 +1337,26 @@
   return cursor_setter_->IsUsingCustomCursor(type);
 }
 
+void CaptureModeSession::UpdateCaptureBarWidgetOpacity(float opacity,
+                                                       bool on_release) {
+  DCHECK(capture_mode_bar_view_);
+  DCHECK(capture_mode_bar_widget_->GetLayer());
+
+  ui::Layer* capture_bar_layer = capture_mode_bar_widget_->GetLayer();
+  if (capture_bar_layer->GetTargetOpacity() == opacity)
+    return;
+
+  ui::ScopedLayerAnimationSettings capture_bar_settings(
+      capture_bar_layer->GetAnimator());
+  capture_bar_settings.SetTransitionDuration(
+      on_release ? kCaptureBarOnReleaseOpacityChangeDuration
+                 : kCaptureBarOpacityChangeDuration);
+  capture_bar_settings.SetTweenType(on_release ? gfx::Tween::FAST_OUT_SLOW_IN
+                                               : gfx::Tween::LINEAR);
+  capture_bar_settings.SetPreemptionStrategy(
+      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+
+  capture_bar_layer->SetOpacity(opacity);
+}
+
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h
index a9269b09..b004a10 100644
--- a/ash/capture_mode/capture_mode_session.h
+++ b/ash/capture_mode/capture_mode_session.h
@@ -128,7 +128,8 @@
                              bool is_event_on_capture_bar);
   void OnLocatedEventDragged(const gfx::Point& location_in_root);
   void OnLocatedEventReleased(const gfx::Point& location_in_root,
-                              bool is_event_on_capture_bar);
+                              bool is_event_on_capture_bar,
+                              bool region_intersects_capture_bar);
 
   // Updates the capture region and the capture region widgets depending on the
   // value of |is_resizing|.
@@ -197,6 +198,10 @@
   // kImage or using custom video capture icon when |type| is kVideo.
   bool IsUsingCustomCursor(CaptureModeType type) const;
 
+  // Updates the capture bar widget with a given opacity. There is a different
+  // animation duration and tween type for mouse/touch release.
+  void UpdateCaptureBarWidgetOpacity(float opacity, bool on_release);
+
   CaptureModeController* const controller_;
 
   // The current root window on which the capture session is active, which may
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc
index 36667258..857be405 100644
--- a/ash/capture_mode/capture_mode_unittests.cc
+++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -1840,4 +1840,61 @@
   histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 2, 1);
 }
 
+// Tests that in Region mode, the capture bar hides and shows itself correctly.
+TEST_F(CaptureModeTest, CaptureBarOpacity) {
+  UpdateDisplay("800x800");
+
+  auto* event_generator = GetEventGenerator();
+  auto* controller = StartImageRegionCapture();
+  EXPECT_TRUE(controller->IsActive());
+
+  ui::Layer* capture_bar_layer = GetCaptureModeBarWidget()->GetLayer();
+
+  // Check to see it starts off opaque.
+  EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
+
+  // Make sure that the bar is transparent when selecting a region.
+  const gfx::Rect target_region(gfx::BoundingRect(
+      gfx::Point(0, 0),
+      GetCaptureModeBarView()->GetBoundsInScreen().top_right() +
+          gfx::Vector2d(0, -50)));
+  event_generator->MoveMouseTo(target_region.origin());
+  event_generator->PressLeftButton();
+  EXPECT_EQ(0.f, capture_bar_layer->GetTargetOpacity());
+  event_generator->MoveMouseTo(target_region.bottom_right());
+  EXPECT_EQ(0.f, capture_bar_layer->GetTargetOpacity());
+  event_generator->ReleaseLeftButton();
+
+  // When there is no overlap of the selected region and the bar, the bar should
+  // be opaque.
+  EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
+
+  // Bar becomes transparent when the region is being moved.
+  event_generator->MoveMouseTo(target_region.origin() + gfx::Vector2d(50, 50));
+  event_generator->PressLeftButton();
+  EXPECT_EQ(0.f, capture_bar_layer->GetTargetOpacity());
+  event_generator->MoveMouseTo(target_region.bottom_center());
+  EXPECT_EQ(0.f, capture_bar_layer->GetTargetOpacity());
+  event_generator->ReleaseLeftButton();
+
+  // The region overlaps the capture bar, so we set the opacity of the bar to
+  // 0.1f.
+  EXPECT_EQ(0.1f, capture_bar_layer->GetTargetOpacity());
+
+  // When there is overlap, the toolbar turns opaque on mouseover.
+  event_generator->MoveMouseTo(
+      GetCaptureModeBarView()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
+
+  // Capture bar drops back to 0.1 opacity when the mouse is no longer hovering.
+  event_generator->MoveMouseTo(
+      GetCaptureModeBarView()->GetBoundsInScreen().top_center() +
+      gfx::Vector2d(0, -50));
+  EXPECT_EQ(0.1f, capture_bar_layer->GetTargetOpacity());
+
+  // Check that the opacity is reset when we select another region.
+  SelectRegion(target_region);
+  EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
+}
+
 }  // namespace ash
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 09175ac8..9e472bef 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -233,9 +233,8 @@
     use_debug_fission == "default" || use_debug_fission || !use_debug_fission,
     "Invalid use_debug_fission.")
 if (use_debug_fission == "default") {
-  use_debug_fission = (is_android && is_official_build) ||
-                      (is_debug && !is_android && !is_fuchsia && !is_apple &&
-                       !is_win && (use_gold || use_lld) && cc_wrapper == "")
+  use_debug_fission = is_debug && !is_android && !is_fuchsia && !is_apple &&
+                      !is_win && (use_gold || use_lld) && cc_wrapper == ""
 }
 
 # If it wasn't manually set, set to an appropriate default.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 4da96db..ee5d2c3b 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201124.2.1
+0.20201124.4.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 4da96db..ee5d2c3b 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201124.2.1
+0.20201124.4.1
diff --git a/chrome/VERSION b/chrome/VERSION
index d4f2fbbb..b311ba4a4 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=89
 MINOR=0
-BUILD=4336
+BUILD=4337
 PATCH=0
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index 28f7aaa..a569585 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -627,7 +627,6 @@
   "java/res/drawable/distilled_page_prefs_button_bg.xml",
   "java/res/drawable/elo_card.xml",
   "java/res/drawable/explore_sites_dense_tile_background.xml",
-  "java/res/drawable/google_pay.xml",
   "java/res/drawable/google_pay_with_divider.xml",
   "java/res/drawable/homepage_promo_illustration_vector.xml",
   "java/res/drawable/ic_add.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index bb5351e..c15d4a00 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -713,6 +713,7 @@
   "java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java",
   "java/src/org/chromium/chrome/browser/infobar/NearOomInfoBar.java",
   "java/src/org/chromium/chrome/browser/infobar/NearOomReductionInfoBar.java",
+  "java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java",
   "java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java",
   "java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java",
   "java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 00fde451..de9c8e3 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -526,11 +526,13 @@
         }
       }
 
+      # Sets ISOLATED_SPLITS_ENABLED in BuildConfig.java.
+      if (_is_bundle_module) {
+        isolated_splits_enabled = enable_isolated_splits
+      }
+
       # Add all loadable modules and shared libraries from DFMs.
       if (_enable_chrome_module) {
-        # Sets ISOLATED_SPLITS_ENABLED in BuildConfig.java.
-        isolated_splits_enabled = true
-
         # The arcore manifest needs to be merged into the base module because the Play
         # Store verifies the com.google.ar.core.min_apk_version meta-data tag is in
         # the base manifest.
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java
index 50de283..e38125b2 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/network_fetch/FeedNewTabPageCardInstrumentationTest.java
@@ -15,7 +15,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -37,7 +36,8 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
 @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS)
-@Features.DisableFeatures(ChromeFeatureList.INTEREST_FEED_V2)
+@Features.DisableFeatures({ChromeFeatureList.INTEREST_FEED_V2,
+        ChromeFeatureList.INTEREST_FEEDV1_CLICKS_AND_VIEWS_CONDITIONAL_UPLOAD})
 public final class FeedNewTabPageCardInstrumentationTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@@ -57,7 +57,6 @@
     @Feature({"FeedNewTabPage", "WPRRecordReplayTest", "RenderTest"})
     @WPRArchiveDirectory("chrome/android/feed/core/javatests/src/org/chromium/chrome/"
             + "browser/feed/wpr_tests")
-    @DisabledTest(message = "http://crbug.com/1152438")
     public void
     launchNTP_withMultipleFeedCardsRendered() throws IOException, InterruptedException {
         mActivityTestRule.loadUrlInNewTab(UrlConstants.NTP_URL);
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 3fefe052..b30872a 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -14,7 +14,8 @@
     xmlns:tools="http://schemas.android.com/tools"
     package="{{ manifest_package }}"
     {% set definitions_in_split = definitions_in_split|default(0) == 'true' %}
-    {% if definitions_in_split %}
+    {% set enable_isolated_splits = enable_isolated_splits|default(0) == 'true' %}
+    {% if enable_isolated_splits %}
     android:isolatedSplits="true"
     {% endif %}
     tools:ignore="MissingVersion">
@@ -154,7 +155,7 @@
     <!-- Set android:largeHeap to "true" to allow more than the default
          Java heap limit (32Mb on Nexus S, 48Mb on Xoom). -->
       <application android:name="{% block application_name %}
-          {%- if definitions_in_split -%}
+          {%- if enable_isolated_splits -%}
           org.chromium.chrome.browser.base.SplitChromeApplication
           {%- else -%}
           org.chromium.chrome.browser.ChromeApplication
@@ -177,7 +178,7 @@
         {% endif %}
         android:networkSecurityConfig="@xml/network_security_config"
         android:allowAudioPlaybackCapture="false"
-        {% if definitions_in_split %}
+        {% if enable_isolated_splits %}
         android:appComponentFactory="org.chromium.chrome.browser.base.SplitCompatAppComponentFactory"
         {% endif %}
         {% block extra_application_attributes %}{% endblock %}>
diff --git a/chrome/android/java/AndroidManifest_monochrome.xml b/chrome/android/java/AndroidManifest_monochrome.xml
index 8a847e8..03f5f41 100644
--- a/chrome/android/java/AndroidManifest_monochrome.xml
+++ b/chrome/android/java/AndroidManifest_monochrome.xml
@@ -9,7 +9,7 @@
 ##
 
 {% block application_name %}
-{%- if definitions_in_split -%}
+{%- if enable_isolated_splits -%}
 org.chromium.chrome.browser.base.SplitMonochromeApplication
 {%- else -%}
 org.chromium.chrome.browser.MonochromeApplication
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java
index 05504f57..82adbe7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java
@@ -18,6 +18,7 @@
 
 /** Utils for compatibility with isolated splits. */
 public class SplitCompatUtils {
+    private static final String CHROME_SPLIT_NAME = "chrome";
     private static final ArraySet<ClassLoader> sInflationClassLoaders = new ArraySet<>();
 
     private SplitCompatUtils() {}
@@ -33,16 +34,20 @@
 
     /** Creates a context which can be used to load code and resources in the chrome split. */
     public static Context createChromeContext(Context base) {
-        return BundleUtils.createIsolatedSplitContext(base, "chrome");
+        if (!BundleUtils.isIsolatedSplitInstalled(base, CHROME_SPLIT_NAME)) {
+            return base;
+        }
+        return BundleUtils.createIsolatedSplitContext(base, CHROME_SPLIT_NAME);
     }
 
     /**
-     * Constructs a new instance of the given class name using the class loader from the context.
+     * Constructs a new instance of the given class name. If the application context class loader
+     * can load the class, that class loader will be used, otherwise the class loader from the
+     * passed in context will be used.
      */
     public static Object newInstance(Context context, String className) {
-        // TODO(crbug.com/1142589): If this crash fix works we can remove the context arg from here.
         Context appContext = ContextUtils.getApplicationContext();
-        if (appContext != null) {
+        if (appContext != null && canLoadClass(appContext.getClassLoader(), className)) {
             context = appContext;
         }
         try {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java
new file mode 100644
index 0000000..74db764
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.infobar;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
+
+/**
+ * Provides helper methods for Android Infobars.
+ */
+class PasswordInfoBarUtils {
+    private PasswordInfoBarUtils() {}
+
+    /**
+     * Creates account indication footer used for Password InfoBars.
+     *
+     * @param context InfoBarLayout's context.
+     * @param accountImage Profile picture or monogram of signed-in user.
+     * @param email E-mail address to be displayed on the footer.
+     * @return Footer view to be added to InfoBar.
+     */
+    static LinearLayout createAccountIndicationFooter(
+            Context context, Bitmap accountImage, String email) {
+        int smallIconSize =
+                context.getResources().getDimensionPixelSize(R.dimen.infobar_small_icon_size);
+        int padding = context.getResources().getDimensionPixelOffset(R.dimen.infobar_padding);
+        LinearLayout footer = (LinearLayout) LayoutInflater.from(context).inflate(
+                R.layout.infobar_footer, null, false);
+
+        TextView emailView = (TextView) footer.findViewById(R.id.infobar_footer_email);
+        emailView.setText(email);
+
+        RoundedCornerImageView profilePicView =
+                (RoundedCornerImageView) footer.findViewById(R.id.infobar_footer_profile_pic);
+        Bitmap resizedProfilePic =
+                Bitmap.createScaledBitmap(accountImage, smallIconSize, smallIconSize, false);
+        profilePicView.setRoundedCorners(
+                smallIconSize / 2, smallIconSize / 2, smallIconSize / 2, smallIconSize / 2);
+        profilePicView.setImageBitmap(resizedProfilePic);
+
+        return footer;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
index 9c37c424..fa704f47 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
@@ -4,17 +4,10 @@
 
 package org.chromium.chrome.browser.infobar;
 
-import android.content.res.Resources;
-import android.graphics.Bitmap;
 import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
 import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
@@ -52,29 +45,10 @@
             detailsMessageLayout.addDescription(mDetailsMessage);
         }
 
-        if (ChromeFeatureList.isEnabled(
-                    ChromeFeatureList.AUTOFILL_ENABLE_PASSWORD_INFO_BAR_ACCOUNT_INDICATION_FOOTER)
-                && mAccountInfo != null && !TextUtils.isEmpty(mAccountInfo.getEmail())
+        if (mAccountInfo != null && !TextUtils.isEmpty(mAccountInfo.getEmail())
                 && mAccountInfo.getAccountImage() != null) {
-            Resources res = layout.getResources();
-            int smallIconSize = res.getDimensionPixelSize(R.dimen.infobar_small_icon_size);
-            int padding = res.getDimensionPixelOffset(R.dimen.infobar_padding);
-
-            LinearLayout footer = (LinearLayout) LayoutInflater.from(layout.getContext())
-                                          .inflate(R.layout.infobar_footer, null, false);
-
-            TextView emailView = (TextView) footer.findViewById(R.id.infobar_footer_email);
-            emailView.setText(mAccountInfo.getEmail());
-
-            RoundedCornerImageView profilePicView =
-                    (RoundedCornerImageView) footer.findViewById(R.id.infobar_footer_profile_pic);
-            Bitmap resizedProfilePic = Bitmap.createScaledBitmap(
-                    mAccountInfo.getAccountImage(), smallIconSize, smallIconSize, false);
-            profilePicView.setRoundedCorners(
-                    smallIconSize / 2, smallIconSize / 2, smallIconSize / 2, smallIconSize / 2);
-            profilePicView.setImageBitmap(resizedProfilePic);
-
-            layout.addFooterView(footer);
+            layout.addFooterView(PasswordInfoBarUtils.createAccountIndicationFooter(
+                    layout.getContext(), mAccountInfo.getAccountImage(), mAccountInfo.getEmail()));
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
index 182f0ba..19562b4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
@@ -14,6 +14,7 @@
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarControlLayout.InfoBarArrayAdapter;
 import org.chromium.components.infobars.InfoBarLayout;
+import org.chromium.components.signin.base.AccountInfo;
 
 /**
  * The Update Password infobar offers the user the ability to update a password for the site.
@@ -22,22 +23,27 @@
     private final String[] mUsernames;
     private final int mUsernameIndex;
     private final String mDetailsMessage;
+    private final AccountInfo mAccountInfo;
     private Spinner mUsernamesSpinner;
 
     @CalledByNative
     private static InfoBar show(int iconId, String[] usernames, int selectedUsername,
-            String message, String detailsMessage, String primaryButtonText) {
-        return new UpdatePasswordInfoBar(
-                iconId, usernames, selectedUsername, message, detailsMessage, primaryButtonText);
+            String message, String detailsMessage, String primaryButtonText,
+            AccountInfo accountInfo) {
+        // If accountInfo is empty, no footer will be shown.
+        return new UpdatePasswordInfoBar(iconId, usernames, selectedUsername, message,
+                detailsMessage, primaryButtonText, accountInfo);
     }
 
     private UpdatePasswordInfoBar(int iconDrawableId, String[] usernames, int selectedUsername,
-            String message, String detailsMessage, String primaryButtonText) {
+            String message, String detailsMessage, String primaryButtonText,
+            AccountInfo accountInfo) {
         super(iconDrawableId, R.color.infobar_icon_drawable_color, null, message, null,
                 primaryButtonText, null);
         mDetailsMessage = detailsMessage;
         mUsernames = usernames;
         mUsernameIndex = selectedUsername;
+        mAccountInfo = accountInfo;
     }
 
     @Override
@@ -59,6 +65,12 @@
             InfoBarControlLayout detailsMessageLayout = layout.addControlLayout();
             detailsMessageLayout.addDescription(mDetailsMessage);
         }
+
+        if (mAccountInfo != null && !TextUtils.isEmpty(mAccountInfo.getEmail())
+                && mAccountInfo.getAccountImage() != null) {
+            layout.addFooterView(PasswordInfoBarUtils.createAccountIndicationFooter(
+                    layout.getContext(), mAccountInfo.getAccountImage(), mAccountInfo.getEmail()));
+        }
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java
index 71a98d5..11e214e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java
@@ -28,12 +28,15 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils.OfflinePageLoadUrlDelegate;
 import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier;
+import org.chromium.chrome.browser.paint_preview.TabbedPaintPreview;
 import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserver;
 import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserver.PerformanceClass;
 import org.chromium.chrome.browser.previews.PreviewsAndroidBridge;
 import org.chromium.chrome.browser.previews.PreviewsUma;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsClient;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabUtils;
 import org.chromium.chrome.browser.ui.favicon.FaviconHelper;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
@@ -238,6 +241,26 @@
      * {@inheritDoc}
      */
     @Override
+    public boolean isShowingPaintPreviewPage() {
+        Tab tab = TabUtils.fromWebContents(mWebContents);
+        return tab != null && TabbedPaintPreview.get(tab).isShowing();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    @Nullable
+    public String getPaintPreviewPageConnectionMessage() {
+        if (!isShowingPaintPreviewPage()) return null;
+
+        return mContext.getString(R.string.page_info_connection_paint_preview);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public boolean shouldShowPerformanceBadge(String url) {
         if (!ChromeFeatureList.isEnabled(ChromeFeatureList.PAGE_INFO_PERFORMANCE_HINTS)) {
             return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
index dd2230d3..910c7b3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
@@ -237,9 +237,11 @@
         if (error != null) return error;
         // Calculate skip ui and build ui only after all payment apps are ready and
         // request.show() is called.
-        mShouldSkipShowingPaymentRequestUi = mPaymentUiService.shouldSkipShowingPaymentRequestUi(
+        mShouldSkipShowingPaymentRequestUi = PaymentUiService.shouldSkipShowingPaymentRequestUi(
                 isUserGestureShow, mDelegate.skipUiForBasicCard(), mSpec.getPaymentOptions(),
-                mSpec.getMethodData().keySet());
+                mSpec.getMethodData().keySet(),
+                (PaymentApp) mPaymentUiService.getSelectedPaymentApp(),
+                mPaymentUiService.getPaymentAppsInPaymentAppList());
         if (!mShouldSkipShowingPaymentRequestUi && mSkipToGPayHelper == null) {
             mPaymentUiService.getPaymentRequestUI().show(isShowWaitingForUpdatedDetails);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
index 61c8979..bc53431 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
@@ -342,6 +342,18 @@
     }
 
     /**
+     * @return Get the payment apps of the PaymentRequest UI in the form of a {@link PaymentApp}
+     *         list.
+     */
+    public List<PaymentApp> getPaymentAppsInPaymentAppList() {
+        List<PaymentApp> paymentApps = new ArrayList<>();
+        for (EditableOption each : mPaymentMethodsSection.getItems()) {
+            paymentApps.add((PaymentApp) each);
+        }
+        return paymentApps;
+    }
+
+    /**
      * Returns the selected payment app, if any.
      * @return The selected payment app or null if none selected.
      */
@@ -1415,21 +1427,19 @@
 
     /**
      * @param options The payment options specified in the payment request.
+     * @param allApps All available payment apps.
      * @return true when there is exactly one available payment app which can provide all requested
      * information including shipping address and payer's contact information whenever needed.
      */
-    public boolean onlySingleAppCanProvideAllRequiredInformation(PaymentOptions options) {
-        assert mPaymentMethodsSection != null;
-
+    private static boolean onlySingleAppCanProvideAllRequiredInformation(
+            PaymentOptions options, List<PaymentApp> allApps) {
         if (!PaymentOptionsUtils.requestAnyInformation(options)) {
-            return mPaymentMethodsSection.getSize() == 1
-                    && !((PaymentApp) mPaymentMethodsSection.getItem(0)).isAutofillInstrument();
+            return allApps.size() == 1 && !((PaymentApp) allApps.get(0)).isAutofillInstrument();
         }
 
         boolean anAppCanProvideAllInfo = false;
-        int sectionSize = mPaymentMethodsSection.getSize();
-        for (int i = 0; i < sectionSize; i++) {
-            PaymentApp app = (PaymentApp) mPaymentMethodsSection.getItem(i);
+        for (int i = 0; i < allApps.size(); i++) {
+            PaymentApp app = (PaymentApp) allApps.get(i);
             if ((!options.requestShipping || app.handlesShippingAddress())
                     && (!options.requestPayerName || app.handlesPayerName())
                     && (!options.requestPayerPhone || app.handlesPayerPhone())
@@ -1490,14 +1500,13 @@
      *         based payment method identifiers (e.g., basic-card).
      * @param options The payment options specified in the payment request.
      * @param paymentMethods The payment methods supported by this request.
+     * @param selectedApp The selected payment apps.
+     * @param allApps All available payment apps.
      * @return Whether the browser payment sheet should be skipped directly into the payment app.
      */
-    public boolean shouldSkipShowingPaymentRequestUi(boolean isUserGestureShow,
+    public static boolean shouldSkipShowingPaymentRequestUi(boolean isUserGestureShow,
             boolean skipUiForNonUrlPaymentMethodIdentifiers, PaymentOptions options,
-            Set<String> paymentMethods) {
-        assert mPaymentMethodsSection != null;
-        PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
-
+            Set<String> paymentMethods, PaymentApp selectedApp, List<PaymentApp> allApps) {
         boolean urlPaymentMethodIdentifiersSupported =
                 isUrlPaymentMethodIdentifiersSupported(paymentMethods);
 
@@ -1509,8 +1518,8 @@
                 // This excludes AutofillPaymentInstrument as its UI is rendered inline in
                 // the payment request UI, thus can't be skipped.
                 && (urlPaymentMethodIdentifiersSupported || skipUiForNonUrlPaymentMethodIdentifiers)
-                && mPaymentMethodsSection.getSize() >= 1
-                && onlySingleAppCanProvideAllRequiredInformation(options)
+                && allApps.size() >= 1
+                && onlySingleAppCanProvideAllRequiredInformation(options, allApps)
                 // Skip to payment app only if it can be pre-selected.
                 && selectedApp != null
                 // Skip to payment app only if user gesture is provided when it is required to
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
index a7fd8a3..61515dd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -39,11 +39,14 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.night_mode.ThemeType;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
+import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
@@ -443,5 +446,31 @@
         expectHasPermissions(url, false);
     }
 
+    /**
+     * Tests that page info view is shown correctly for paint preview pages.
+     */
+    @Test
+    @MediumTest
+    @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2)
+    public void testPaintPreview() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            final ChromeActivity activity = mActivityTestRule.getActivity();
+            final Tab tab = activity.getActivityTab();
+            ChromePageInfoControllerDelegate pageInfoControllerDelegate =
+                    new ChromePageInfoControllerDelegate(activity, tab.getWebContents(),
+                            activity::getModalDialogManager,
+                            new OfflinePageUtils.TabOfflinePageLoadUrlDelegate(tab)) {
+                        @Override
+                        public boolean isShowingPaintPreviewPage() {
+                            return true;
+                        }
+                    };
+            PageInfoController.show(mActivityTestRule.getActivity(), tab.getWebContents(), null,
+                    PageInfoController.OpenedFromSource.MENU, pageInfoControllerDelegate,
+                    new ChromePermissionParamsListBuilderDelegate());
+        });
+        onView(withText(R.string.page_info_connection_paint_preview)).check(matches(isDisplayed()));
+    }
+
     // TODO(1071762): Add tests for preview pages, offline pages, offline state and other states.
 }
diff --git a/chrome/android/modules/buildflags.gni b/chrome/android/modules/buildflags.gni
index 2cc34bd..b578193 100644
--- a/chrome/android/modules/buildflags.gni
+++ b/chrome/android/modules/buildflags.gni
@@ -21,6 +21,12 @@
   enable_chrome_child_modules = true
 }
 
+declare_args() {
+  # Whether isolated splits are enabled. This can be enabled/disabled separately
+  # from enable_chrome_module to test performance in various configurations.
+  enable_isolated_splits = enable_chrome_module
+}
+
 # If true, lld is used to partition feature code into separate libraries, which
 # in turn are included in Dynamic Feature Modules.
 use_native_partitions = is_android && is_clang && use_lld && !is_component_build
diff --git a/chrome/android/monochrome_android_manifest_jinja_variables.gni b/chrome/android/monochrome_android_manifest_jinja_variables.gni
index 8a0c958..7428fe7 100644
--- a/chrome/android/monochrome_android_manifest_jinja_variables.gni
+++ b/chrome/android/monochrome_android_manifest_jinja_variables.gni
@@ -2,10 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//chrome/android/modules/buildflags.gni")
+
 use_32bit_abi_jinja_variable = "use32bitAbi=android:use32bitAbi=\"true\""
 
 monochrome_android_manifest_jinja_variables = [
   "min_sdk_version=24",
   "sandboxed_service_exported=true",
   use_32bit_abi_jinja_variable,
+  "enable_isolated_splits=$enable_isolated_splits",
 ]
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index 94ba125a..24498ac 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -6,6 +6,7 @@
 import("//build/config/android/rules.gni")
 import("//build/util/version.gni")
 import("//chrome/android/chrome_public_apk_tmpl.gni")
+import("//chrome/android/modules/buildflags.gni")
 
 if (!defined(default_trichrome_certdigest)) {
   default_trichrome_certdigest =
@@ -32,6 +33,7 @@
   "trichrome_library=$trichrome_library_package",
   "trichrome_certdigest=$trichrome_certdigest",
   "use32bitAbi=android:use32bitAbi=\"true\"",
+  "enable_isolated_splits=$enable_isolated_splits",
 ]
 
 trichrome_synchronized_proguard =
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 4780b7d8..92772b1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1196,7 +1196,7 @@
           R&amp;eopen closed window
         </message>
         <message name="IDS_NAME_WINDOW" desc="The text label of the Name Window menu item, used to give a user-specified name to a window.">
-          &amp;Name window...
+          Name &amp;window...
         </message>
       </if>
       <if expr="use_titlecase">
@@ -1231,7 +1231,7 @@
           R&amp;eopen Closed Window
         </message>
         <message name="IDS_NAME_WINDOW" desc="In Title Case: The text label of the Name Window menu item, used to give a user-specified name to a window.">
-          &amp;Name Window...
+          Name &amp;Window...
         </message>
       </if>
 
diff --git a/chrome/app/generated_resources_grd/IDS_NAME_WINDOW.png.sha1 b/chrome/app/generated_resources_grd/IDS_NAME_WINDOW.png.sha1
index 6282dff..b48c8929 100644
--- a/chrome/app/generated_resources_grd/IDS_NAME_WINDOW.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_NAME_WINDOW.png.sha1
@@ -1 +1 @@
-cfa733e851c5851c6bb1553d6a450c8dce471a03
\ No newline at end of file
+63c80481339ded5dbab86d7b374fb6e58e8af86c
\ No newline at end of file
diff --git a/chrome/app/nearby_share_strings.grdp b/chrome/app/nearby_share_strings.grdp
index c600af7..1b1662a7 100644
--- a/chrome/app/nearby_share_strings.grdp
+++ b/chrome/app/nearby_share_strings.grdp
@@ -25,6 +25,12 @@
   <message name="IDS_NEARBY_CONTACT_VISIBILITY_NO_CONTACTS_TITLE" desc="Title text shown when there are no reachable contacts with a Google Account to select from.">
     No reachable contacts
   </message>
+  <message name="IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE" desc="Informational message indicating that there are contacts that are not connectable for sharing with the Nearby Share feature.">
+    {COUNT, plural,
+      =1 {# contact is not available. To use Nearby Share with them, add the email address associated with their Google Account to your contacts.}
+      other {# contacts are not available. To use Nearby Share with them, add the email address associated with their Google Account to your contacts.}
+    }
+  </message>
   <message name="IDS_NEARBY_CONTACT_VISIBILITY_OTHERS" desc="Describes when nearby devices are visible to this user when using the Nearby Share feature.">
     People who have chosen to be visible to you when their screen is unlocked and devices near you when Nearby Share is open
   </message>
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE.png.sha1
new file mode 100644
index 0000000..e2de107
--- /dev/null
+++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE.png.sha1
@@ -0,0 +1 @@
+ed8290079c6a8322f04de43996154eb3fdd0068b
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7188781..b053344 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3099,6 +3099,8 @@
       "password_manager/android/password_generation_controller_impl.cc",
       "password_manager/android/password_generation_controller_impl.h",
       "password_manager/android/password_generation_dialog_view_interface.h",
+      "password_manager/android/password_infobar_utils.cc",
+      "password_manager/android/password_infobar_utils.h",
       "password_manager/android/password_manager_infobar_delegate_android.cc",
       "password_manager/android/password_manager_infobar_delegate_android.h",
       "password_manager/android/password_manager_launcher_android.cc",
@@ -3601,6 +3603,8 @@
       "media/kaleidoscope/constants.h",
       "media/kaleidoscope/kaleidoscope_data_provider_impl.cc",
       "media/kaleidoscope/kaleidoscope_data_provider_impl.h",
+      "media/kaleidoscope/kaleidoscope_identity_manager_impl.cc",
+      "media/kaleidoscope/kaleidoscope_identity_manager_impl.h",
       "media/kaleidoscope/kaleidoscope_metrics_recorder.cc",
       "media/kaleidoscope/kaleidoscope_metrics_recorder.h",
       "media/kaleidoscope/kaleidoscope_prefs.cc",
@@ -4140,6 +4144,7 @@
         "sharing/webrtc/sharing_mojo_service.h",
       ]
       deps += [
+        "//build:chromeos_buildflags",
         "//chrome/browser/supervised_user:supervised_user_unscaled_resources",
         "//chrome/services/sharing/public/cpp",
         "//chrome/services/sharing/public/proto",
@@ -6640,6 +6645,7 @@
     "//chrome/browser/ui:test_support",
   ]
   deps = [
+    "//build:chromeos_buildflags",
     "//chrome/app/theme:theme_resources",
     "//chrome/browser",
     "//chrome/browser:browser_process",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1d3fdf8..7335cb0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1510,9 +1510,20 @@
          kPromoBrowserCommandOpenSafeBrowsingSettingsEnhancedProtectionCommandParam),
      nullptr}};
 #if !defined(OS_ANDROID)
+
+const FeatureEntry::FeatureParam kNtpRecipeTasksModuleFakeData[] = {
+    {ntp_features::kNtpStatefulTasksModuleDataParam, "fake"}};
+const FeatureEntry::FeatureVariation kNtpRecipeTasksModuleVariations[] = {
+    {"- Fake Data", kNtpRecipeTasksModuleFakeData,
+     base::size(kNtpRecipeTasksModuleFakeData), nullptr},
+};
+
+const FeatureEntry::FeatureParam kNtpShoppingTasksModuleFakeData[] = {
+    {ntp_features::kNtpStatefulTasksModuleDataParam, "fake"}};
 const FeatureEntry::FeatureVariation kNtpShoppingTasksModuleVariations[] = {
-    {"- Real Data", {}, 0, "t3329137" /* variation_id */},
-    {"- Fake Data", {}, 0, "t3329139" /* variation_id */},
+    {"- Fake Data", kNtpShoppingTasksModuleFakeData,
+     base::size(kNtpShoppingTasksModuleFakeData),
+     "t3329139" /* variation_id */},
 };
 
 const FeatureEntry::FeatureParam kNtpRepeatableQueriesInsertPositionStart[] = {
@@ -2441,6 +2452,13 @@
      kSubresourceRedirectLoginRobotsBasedCompression,
      base::size(kSubresourceRedirectLoginRobotsBasedCompression), nullptr}};
 
+#if defined(OS_CHROMEOS)
+const FeatureEntry::FeatureVariation
+    kOmniboxRichEntitiesInLauncherVariations[] = {
+        {"with linked Suggest experiment", {}, 0, "t4461027"},
+};
+#endif  // OS_CHROMEOS
+
 // RECORDING USER METRICS FOR FLAGS:
 // -----------------------------------------------------------------------------
 // The first line of the entry is the internal name.
@@ -4398,7 +4416,9 @@
 
     {"ntp-recipe-tasks-module", flag_descriptions::kNtpRecipeTasksModuleName,
      flag_descriptions::kNtpRecipeTasksModuleDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(ntp_features::kNtpRecipeTasksModule)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(ntp_features::kNtpRecipeTasksModule,
+                                    kNtpRecipeTasksModuleVariations,
+                                    "NtpRecipeTasksModule")},
 
     {"ntp-shopping-tasks-module",
      flag_descriptions::kNtpShoppingTasksModuleName,
@@ -6628,7 +6648,10 @@
     {"omnibox-rich-entities-in-launcher",
      flag_descriptions::kOmniboxRichEntitiesInLauncherName,
      flag_descriptions::kOmniboxRichEntitiesInLauncherDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(app_list_features::kEnableOmniboxRichEntities)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         app_list_features::kEnableOmniboxRichEntities,
+         kOmniboxRichEntitiesInLauncherVariations,
+         "OmniboxRichEntitiesInLauncher")},
 
     {"separate-pointing-stick-settings",
      flag_descriptions::kSeparatePointingStickSettingsName,
diff --git a/chrome/browser/apps/app_service/BUILD.gn b/chrome/browser/apps/app_service/BUILD.gn
index 9c59a197..b52263e 100644
--- a/chrome/browser/apps/app_service/BUILD.gn
+++ b/chrome/browser/apps/app_service/BUILD.gn
@@ -11,6 +11,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//chrome/test:test_support",
     "//skia",
   ]
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc
index 23fc909..cf8a22a 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -20,6 +20,7 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/dip_px_util.h"
 #include "chrome/browser/extensions/chrome_app_icon.h"
 #include "chrome/browser/extensions/chrome_app_icon_loader.h"
@@ -53,7 +54,7 @@
 #include "ui/gfx/image/image_skia_operations.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/ui/app_list/icon_standardizer.h"
 #include "chrome/browser/ui/app_list/md_icon_normalizer.h"
@@ -66,7 +67,7 @@
 
 static const int kInvalidIconResource = 0;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Copy from Android code, all four sides of the ARC foreground and background
 // images are padded 25% of it's width and height.
@@ -314,7 +315,7 @@
     }
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon) &&
       icon_manager.HasSmallestIcon(web_app_id, {IconPurpose::MASKABLE},
                                    max_icon_size_in_px)) {
@@ -404,7 +405,7 @@
 
   void LoadIconFromResource(int icon_resource);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // For ARC icons, converts an icon png data to an ImageSkia using
   // arc::IconDecodeRequest.
   void LoadArcIconPngData(const std::vector<uint8_t>& icon_png_data);
@@ -417,7 +418,7 @@
   // Loads icons for ARC activities.
   void LoadArcActivityIcons(
       const std::vector<arc::mojom::ActivityIconPtr>& icons);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
  private:
   friend class base::RefCounted<IconLoadingPipeline>;
@@ -435,7 +436,7 @@
     }
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<arc::IconDecodeRequest> CreateArcIconDecodeRequest(
       base::OnceCallback<void(const gfx::ImageSkia& icon)> callback,
       const std::vector<uint8_t>& icon_png_data);
@@ -447,7 +448,7 @@
 
   void OnArcActivityIconLoaded(gfx::ImageSkia* arc_activity_icon,
                                const gfx::ImageSkia& icon);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   void MaybeApplyEffectsAndComplete(const gfx::ImageSkia image);
 
@@ -503,11 +504,11 @@
   base::OnceCallback<void(const std::vector<gfx::ImageSkia>& icon)>
       arc_activity_icons_callback_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<arc::IconDecodeRequest> arc_icon_decode_request_;
   std::unique_ptr<arc::IconDecodeRequest> arc_foreground_icon_decode_request_;
   std::unique_ptr<arc::IconDecodeRequest> arc_background_icon_decode_request_;
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 void IconLoadingPipeline::LoadWebAppIcon(
@@ -695,7 +696,7 @@
 void IconLoadingPipeline::LoadIconFromResource(int icon_resource) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (icon_resource == IDR_LOGO_CROSTINI_DEFAULT_192 ||
       icon_resource == IDR_APP_DEFAULT_ICON) {
     // For the Crostini penguin icon, clear the standard icon effects, and use
@@ -762,7 +763,7 @@
   MaybeLoadFallbackOrCompleteEmpty();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void IconLoadingPipeline::LoadArcIconPngData(
     const std::vector<uint8_t>& icon_png_data) {
   arc_icon_decode_request_ = CreateArcIconDecodeRequest(
@@ -874,7 +875,7 @@
     std::move(arc_activity_icons_callback_).Run(arc_activity_icons_);
   }
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void IconLoadingPipeline::MaybeApplyEffectsAndComplete(
     const gfx::ImageSkia image) {
@@ -1094,7 +1095,7 @@
   return image_data;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size) {
   gfx::ImageSkia mask_image;
@@ -1199,13 +1200,13 @@
       base::MakeRefCounted<IconLoadingPipeline>(std::move(callback));
   icon_loader->LoadArcActivityIcons(icons);
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void ApplyIconEffects(IconEffects icon_effects,
                       int size_hint_in_dip,
                       gfx::ImageSkia* image_skia) {
   extensions::ChromeAppIcon::ResizeFunction resize_function;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (icon_effects & IconEffects::kResizeAndPad) {
     // TODO(crbug.com/826982): MD post-processing is not always applied: "See
     // legacy code:
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h
index 5aae37c..04ee917 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.h
+++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -11,15 +11,16 @@
 
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/components/app_registrar.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/gfx/image/image_skia.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/arc/mojom/app.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace content {
 class BrowserContext;
@@ -90,7 +91,7 @@
 std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image,
                                            float rep_icon_scale);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size);
 
 gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image);
@@ -108,7 +109,7 @@
     const std::vector<arc::mojom::ActivityIconPtr>& icons,
     base::OnceCallback<void(const std::vector<gfx::ImageSkia>& icons)>
         callback);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Modifies |image_skia| to apply icon post-processing effects like badging and
 // desaturation to gray.
diff --git a/chrome/browser/apps/app_service/app_icon_factory_unittest.cc b/chrome/browser/apps/app_service/app_icon_factory_unittest.cc
index 8ad0fc1..4e89b767 100644
--- a/chrome/browser/apps/app_service/app_icon_factory_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/test/pixel_comparator.h"
 #include "cc/test/pixel_test_utils.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
@@ -41,7 +42,7 @@
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/ui/app_list/icon_standardizer.h"
 #include "chrome/browser/ui/app_list/md_icon_normalizer.h"
@@ -197,7 +198,7 @@
 
     output_image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(decoded, scale));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
       output_image_skia = app_list::CreateStandardIconImage(output_image_skia);
     }
@@ -205,7 +206,7 @@
     EnsureRepresentationsLoaded(output_image_skia);
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void RunLoadIconFromResource(apps::mojom::IconType icon_type,
                                apps::IconEffects icon_effects,
                                apps::mojom::IconValuePtr& output_icon) {
@@ -352,7 +353,7 @@
       result->uncompressed.GetRepresentation(scale).GetBitmap()));
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(AppIconFactoryTest, LoadCrostiniPenguinIcon) {
   auto icon_type = apps::mojom::IconType::kUncompressed;
   auto icon_effects = apps::IconEffects::kNone;
@@ -614,7 +615,7 @@
     run_loop.Run();
 
     extensions::ChromeAppIcon::ResizeFunction resize_function;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
       if (purpose == IconPurpose::ANY) {
         output_image_skia =
@@ -663,7 +664,7 @@
     base::RunLoop run_loop;
 
     auto icon_type = apps::mojom::IconType::kUncompressed;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
       icon_type = apps::mojom::IconType::kStandard;
     }
@@ -736,7 +737,7 @@
   gfx::ImageSkia dst_image_skia;
   apps::IconEffects icon_effect = apps::IconEffects::kRoundCorners;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     icon_effect |= apps::IconEffects::kCrOsStandardIcon;
   } else {
@@ -772,7 +773,7 @@
   apps::mojom::IconValuePtr icon;
   apps::IconEffects icon_effect = apps::IconEffects::kRoundCorners;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     icon_effect |= apps::IconEffects::kCrOsStandardIcon;
   } else {
@@ -801,7 +802,7 @@
 
   RegisterApp(std::move(web_app));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     ASSERT_TRUE(
         icon_manager().HasIcons(app_id, IconPurpose::MASKABLE, {kIconSize2}));
@@ -852,7 +853,7 @@
   std::vector<uint8_t> src_data;
   apps::mojom::IconValuePtr icon;
   apps::IconEffects icon_effect = apps::IconEffects::kRoundCorners;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     icon_effect |= apps::IconEffects::kCrOsStandardBackground |
                    apps::IconEffects::kCrOsStandardMask;
@@ -907,7 +908,7 @@
   gfx::ImageSkia dst_image_skia;
   apps::IconEffects icon_effect = apps::IconEffects::kRoundCorners;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     icon_effect |= apps::IconEffects::kCrOsStandardIcon;
   } else {
@@ -979,7 +980,7 @@
   gfx::ImageSkia dst_image_skia;
   apps::IconEffects icon_effect = apps::IconEffects::kRoundCorners;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
     icon_effect |= apps::IconEffects::kCrOsStandardIcon;
   } else {
diff --git a/chrome/browser/apps/app_service/app_service_metrics.cc b/chrome/browser/apps/app_service/app_service_metrics.cc
index b587b070..f5a51a5 100644
--- a/chrome/browser/apps/app_service/app_service_metrics.cc
+++ b/chrome/browser/apps/app_service/app_service_metrics.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/file_manager/app_id.h"
 #include "chrome/browser/web_applications/components/web_app_id_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -14,10 +15,10 @@
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "extensions/common/constants.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -209,19 +210,19 @@
     RecordDefaultAppLaunch(DefaultAppName::kDocs, launch_source);
   else if (app_id == extension_misc::kDriveHostedAppId)
     RecordDefaultAppLaunch(DefaultAppName::kDrive, launch_source);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == arc::kGoogleDuoAppId)
     RecordDefaultAppLaunch(DefaultAppName::kDuo, launch_source);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == extension_misc::kFilesManagerAppId)
     RecordDefaultAppLaunch(DefaultAppName::kFiles, launch_source);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == extension_misc::kGmailAppId || app_id == arc::kGmailAppId)
     RecordDefaultAppLaunch(DefaultAppName::kGmail, launch_source);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == extension_misc::kGoogleKeepAppId)
     RecordDefaultAppLaunch(DefaultAppName::kKeep, launch_source);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == extension_misc::kGooglePhotosAppId)
     RecordDefaultAppLaunch(DefaultAppName::kPhotos, launch_source);
   else if (app_id == arc::kPlayBooksAppId)
@@ -236,7 +237,7 @@
     RecordDefaultAppLaunch(DefaultAppName::kPlayMusic, launch_source);
   else if (app_id == arc::kPlayStoreAppId)
     RecordDefaultAppLaunch(DefaultAppName::kPlayStore, launch_source);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == web_app::kOsSettingsAppId)
     RecordDefaultAppLaunch(DefaultAppName::kSettings, launch_source);
   else if (app_id == extension_misc::kGoogleSheetsAppId)
@@ -245,11 +246,11 @@
     RecordDefaultAppLaunch(DefaultAppName::kSlides, launch_source);
   else if (app_id == extensions::kWebStoreAppId)
     RecordDefaultAppLaunch(DefaultAppName::kWebStore, launch_source);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == extension_misc::kYoutubeAppId ||
            app_id == arc::kYoutubeAppId)
     RecordDefaultAppLaunch(DefaultAppName::kYouTube, launch_source);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   else if (app_id == web_app::kYoutubeMusicAppId)
     RecordDefaultAppLaunch(DefaultAppName::kYouTubeMusic, launch_source);
   else if (app_id == web_app::kStadiaAppId)
@@ -264,10 +265,10 @@
     RecordBuiltInAppLaunch(BuiltInAppName::kSettings, launch_source);
   } else if (app_id == ash::kInternalAppIdContinueReading) {
     RecordBuiltInAppLaunch(BuiltInAppName::kContinueReading, launch_source);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (app_id == plugin_vm::kPluginVmShelfAppId) {
     RecordBuiltInAppLaunch(BuiltInAppName::kPluginVm, launch_source);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (app_id == ash::kReleaseNotesAppId) {
     RecordBuiltInAppLaunch(BuiltInAppName::kReleaseNotes, launch_source);
   } else if (app_id == web_app::kMockSystemAppId) {
@@ -285,11 +286,11 @@
   } else if (app_id == ash::kInternalAppIdContinueReading) {
     base::UmaHistogramEnumeration("Apps.AppListSearchResultInternalApp.Show",
                                   BuiltInAppName::kContinueReading);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (app_id == plugin_vm::kPluginVmShelfAppId) {
     base::UmaHistogramEnumeration("Apps.AppListSearchResultInternalApp.Show",
                                   BuiltInAppName::kPluginVm);
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (app_id == ash::kReleaseNotesAppId) {
     base::UmaHistogramEnumeration("Apps.AppListSearchResultInternalApp.Show",
                                   BuiltInAppName::kReleaseNotes);
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc
index 8de93d3..c80da70 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_icon_source.h"
 #include "chrome/browser/apps/app_service/app_service_metrics.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -30,7 +31,7 @@
 #include "ui/display/types/display_constants.h"
 #include "url/url_constants.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/apps/app_service/lacros_apps.h"
 #include "chrome/browser/apps/app_service/uninstall_dialog.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limit_interface.h"
@@ -109,7 +110,7 @@
 }
 
 AppServiceProxy::~AppServiceProxy() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   AppRegistryCacheWrapper::Get().RemoveAppRegistryCache(&cache_);
 #endif
 }
@@ -136,7 +137,7 @@
     return;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const user_manager::User* user =
       chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
   if (user) {
@@ -160,7 +161,7 @@
     receivers_.Add(this, subscriber.InitWithNewPipeAndPassReceiver());
     app_service_->RegisterSubscriber(std::move(subscriber), nullptr);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // The AppServiceProxy is also a publisher, of a variety of app types. That
     // responsibility isn't intrinsically part of the AppServiceProxy, but doing
     // that here, for each such app type, is as good a place as any.
@@ -211,7 +212,7 @@
   return cache_;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 apps::InstanceRegistry& AppServiceProxy::InstanceRegistry() {
   return instance_registry_;
 }
@@ -250,7 +251,7 @@
   if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this, event_flags, launch_source,
                               display_id](const apps::AppUpdate& update) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       if (MaybeShowLaunchPreventionDialog(update)) {
         return;
       }
@@ -277,7 +278,7 @@
   if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this, container, event_flags, launch_source,
                               &file_paths](const apps::AppUpdate& update) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       if (MaybeShowLaunchPreventionDialog(update)) {
         return;
       }
@@ -315,7 +316,7 @@
   if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this, event_flags, &intent, launch_source,
                               display_id](const apps::AppUpdate& update) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       if (MaybeShowLaunchPreventionDialog(update)) {
         return;
       }
@@ -356,7 +357,7 @@
 
 void AppServiceProxy::Uninstall(const std::string& app_id,
                                 gfx::NativeWindow parent_window) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   UninstallImpl(app_id, parent_window, base::DoNothing());
 #else
   // On non-ChromeOS, publishers run the remove dialog.
@@ -376,7 +377,7 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void AppServiceProxy::PauseApps(
     const std::map<std::string, PauseData>& pause_data) {
   if (!app_service_.is_connected()) {
@@ -426,7 +427,7 @@
     app_service_->UnpauseApps(app_type, app_id);
   }
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void AppServiceProxy::StopApp(const std::string& app_id) {
   if (!app_service_.is_connected()) {
@@ -473,7 +474,7 @@
 
 void AppServiceProxy::FlushMojoCallsForTesting() {
   app_service_impl_->FlushMojoCallsForTesting();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (built_in_chrome_os_apps_)
     built_in_chrome_os_apps_->FlushMojoCallsForTesting();
   crostini_apps_->FlushMojoCallsForTesting();
@@ -501,7 +502,7 @@
   return old;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void AppServiceProxy::ReInitializeCrostiniForTesting(Profile* profile) {
   if (app_service_.is_connected()) {
     crostini_apps_->ReInitializeForTesting(app_service_, profile);
@@ -585,7 +586,7 @@
 }
 
 void AppServiceProxy::SetArcIsRegistered() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (arc_is_registered_) {
     return;
   }
@@ -631,7 +632,7 @@
 }
 
 void AppServiceProxy::Shutdown() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   uninstall_dialogs_.clear();
 
   if (app_service_.is_connected()) {
@@ -670,7 +671,7 @@
   preferred_apps_.Init(preferred_apps);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void AppServiceProxy::UninstallImpl(const std::string& app_id,
                                     gfx::NativeWindow parent_window,
                                     base::OnceClosure callback) {
@@ -846,17 +847,17 @@
     app_service_->PauseApp(app_type, app_id);
   }
 }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void AppServiceProxy::OnAppUpdate(const apps::AppUpdate& update) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if ((update.PausedChanged() &&
        update.Paused() == apps::mojom::OptionalBool::kTrue) ||
       (update.ReadinessChanged() &&
        update.Readiness() == apps::mojom::Readiness::kUninstalledByUser)) {
     pending_pause_requests_.MaybeRemoveApp(update.AppId());
   }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   if (!update.ReadinessChanged() ||
       update.Readiness() != apps::mojom::Readiness::kUninstalledByUser) {
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h
index 9cc8e44..137d1376 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.h
+++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -14,6 +14,7 @@
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
@@ -26,7 +27,7 @@
 #include "ui/gfx/native_widget_types.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/apps/app_service/borealis_apps.h"
 #include "chrome/browser/apps/app_service/built_in_chromeos_apps.h"
 #include "chrome/browser/apps/app_service/crostini_apps.h"
@@ -37,7 +38,7 @@
 #else
 #include "chrome/browser/apps/app_service/extension_apps.h"
 #include "chrome/browser/apps/app_service/web_apps.h"
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 class Profile;
 
@@ -45,7 +46,7 @@
 
 class AppServiceImpl;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class LacrosApps;
 class UninstallDialog;
 
@@ -78,7 +79,7 @@
                         public apps::mojom::Subscriber,
                         public apps::AppRegistryCache::Observer {
  public:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   using OnPauseDialogClosedCallback = base::OnceCallback<void()>;
 #endif
 
@@ -90,7 +91,7 @@
   mojo::Remote<apps::mojom::AppService>& AppService();
   apps::AppRegistryCache& AppRegistryCache();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   apps::InstanceRegistry& InstanceRegistry();
 #endif
 
@@ -180,7 +181,7 @@
   void UninstallSilently(const std::string& app_id,
                          apps::mojom::UninstallSource uninstall_source);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Pauses apps. |pause_data|'s key is the app_id. |pause_data|'s PauseData
   // is the time limit setting for the app, which is shown in the pause app
   // dialog. AppService sets the paused status directly. If the app is running,
@@ -217,7 +218,7 @@
   void FlushMojoCallsForTesting();
   apps::IconLoader* OverrideInnerIconLoaderForTesting(
       apps::IconLoader* icon_loader);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void ReInitializeCrostiniForTesting(Profile* profile);
   void SetDialogCreatedCallbackForTesting(base::OnceClosure callback);
   void UninstallForTesting(const std::string& app_id,
@@ -316,7 +317,7 @@
     apps::IconLoader* overriding_icon_loader_for_testing_;
   };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   static void CreateBlockDialog(const std::string& app_name,
                                 const gfx::ImageSkia& image,
                                 Profile* profile);
@@ -346,7 +347,7 @@
   void InitializePreferredApps(
       PreferredAppsList::PreferredApps preferred_apps) override;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void UninstallImpl(const std::string& app_id,
                      gfx::NativeWindow parent_window,
                      base::OnceClosure callback);
@@ -419,7 +420,7 @@
 
   apps::PreferredAppsList preferred_apps_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<BuiltInChromeOsApps> built_in_chrome_os_apps_;
   std::unique_ptr<CrostiniApps> crostini_apps_;
   std::unique_ptr<ExtensionAppsChromeOs> extension_apps_;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_factory.cc b/chrome/browser/apps/app_service/app_service_proxy_factory.cc
index c1c23ff..d156ee40 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_factory.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_factory.cc
@@ -6,6 +6,7 @@
 
 #include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
@@ -16,12 +17,12 @@
 #include "extensions/browser/extension_prefs_factory.h"
 #include "extensions/browser/extension_registry_factory.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "extensions/browser/app_window/app_window_registry.h"
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace apps {
 
@@ -39,7 +40,7 @@
   // user's browsing data from incognito to an app. Clients of the App Service
   // should explicitly decide when it is and isn't appropriate to use the
   // associated real profile and pass that to this method.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // An exception on Chrome OS is the guest profile, which is incognito, but
   // can have apps within it.
   return (!chromeos::ProfileHelper::IsSigninProfile(profile) &&
@@ -98,11 +99,11 @@
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
   DependsOn(HostContentSettingsMapFactory::GetInstance());
   DependsOn(web_app::WebAppProviderFactory::GetInstance());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   DependsOn(guest_os::GuestOsRegistryServiceFactory::GetInstance());
   DependsOn(NotificationDisplayServiceFactory::GetInstance());
   DependsOn(extensions::AppWindowRegistry::Factory::GetInstance());
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 AppServiceProxyFactory::~AppServiceProxyFactory() = default;
@@ -119,7 +120,7 @@
     return nullptr;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
     return nullptr;
   }
@@ -129,7 +130,7 @@
   if (profile->IsGuestSession()) {
     return chrome::GetBrowserContextOwnInstanceInIncognito(context);
   }
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // TODO(https://crbug.com/1122463): replace this with
   // BrowserContextKeyedServiceFactory::GetBrowserContextToUse(context) once
diff --git a/chrome/browser/apps/app_service/app_service_test.cc b/chrome/browser/apps/app_service/app_service_test.cc
index 25de00d..8526fac 100644
--- a/chrome/browser/apps/app_service/app_service_test.cc
+++ b/chrome/browser/apps/app_service/app_service_test.cc
@@ -5,14 +5,15 @@
 #include "chrome/browser/apps/app_service/app_service_test.h"
 
 #include "base/run_loop.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/apps/app_service/arc_apps.h"
 #include "chrome/browser/apps/app_service/arc_apps_factory.h"
-#endif  // OS_CHROMEOS
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace apps {
 
diff --git a/chrome/browser/apps/app_service/extension_apps_base.cc b/chrome/browser/apps/app_service/extension_apps_base.cc
index 3d88f60..70a691c1 100644
--- a/chrome/browser/apps/app_service/extension_apps_base.cc
+++ b/chrome/browser/apps/app_service/extension_apps_base.cc
@@ -17,6 +17,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
 #include "chrome/browser/apps/app_service/extension_uninstaller.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
@@ -224,7 +225,7 @@
 void ExtensionAppsBase::SetShowInFields(
     apps::mojom::AppPtr& app,
     const extensions::Extension* extension) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (extension->id() == extension_misc::kWallpaperManagerId) {
     // Explicitly show the Wallpaper Picker app in search only.
     app->show_in_launcher = apps::mojom::OptionalBool::kFalse;
@@ -233,7 +234,7 @@
     app->show_in_management = apps::mojom::OptionalBool::kFalse;
     return;
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   if (ShouldShow(extension, profile_)) {
     auto show = ShouldShownInLauncher(extension)
                     ? apps::mojom::OptionalBool::kTrue
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index c000f250..e28f921f 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/chrome_content_browser_client.h"
@@ -2107,7 +2108,8 @@
 // The test launches an app with guest and closes the window on loadcommit. It
 // then launches the app window again. The process is repeated 3 times.
 // TODO(crbug.com/949923): The test is flaky (crash) on ChromeOS debug and ASan/LSan
-#if defined(OS_CHROMEOS) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
+#if BUILDFLAG(IS_CHROMEOS_ASH) && \
+    (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
 #define MAYBE_CloseOnLoadcommit DISABLED_CloseOnLoadcommit
 #else
 #define MAYBE_CloseOnLoadcommit CloseOnLoadcommit
@@ -2930,7 +2932,7 @@
 #else
 #define MAYBE_DownloadCookieIsolation_CrossSession \
   DownloadCookieIsolation_CrossSession
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 IN_PROC_BROWSER_TEST_F(WebViewTest,
                        MAYBE_DownloadCookieIsolation_CrossSession) {
@@ -3194,7 +3196,11 @@
 };
 
 // https://crbug.com/1087381
-#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(ADDRESS_SANITIZER))
+// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
+// complete.
+#if defined(OS_CHROMEOS) ||                                  \
+    ((defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     defined(ADDRESS_SANITIZER))
 #define MAYBE_Shim_TestZoomAPI DISABLED_Shim_TestZoomAPI
 #else
 #define MAYBE_Shim_TestZoomAPI Shim_TestZoomAPI
@@ -4116,7 +4122,9 @@
   }
 };
 
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MAC) || \
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || defined(OS_MAC) || \
     defined(OS_WIN)
 // This verifies the fix for http://crbug.com/667708.
 IN_PROC_BROWSER_TEST_F(ChromeSignInWebViewTest,
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
index 4894583..28e367f 100644
--- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -609,7 +610,9 @@
 // crbug.com/341876
 
 // Timeouts flakily: crbug.com/1003345
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest,
                        DISABLED_PointerLock) {
   SetupTest("web_view/pointer_lock",
@@ -706,7 +709,7 @@
   ASSERT_TRUE(unlocked_listener.WaitUntilSatisfied());
 }
 
-#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
 // Tests that if a <webview> is focused before navigation then the guest starts
 // off focused.
diff --git a/chrome/browser/apps/platform_apps/BUILD.gn b/chrome/browser/apps/platform_apps/BUILD.gn
index f126569d..35550a1 100644
--- a/chrome/browser/apps/platform_apps/BUILD.gn
+++ b/chrome/browser/apps/platform_apps/BUILD.gn
@@ -50,6 +50,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//chrome/app:command_ids",
     "//chrome/browser:browser_process",
     "//chrome/browser/extensions",
diff --git a/chrome/browser/apps/platform_apps/api/BUILD.gn b/chrome/browser/apps/platform_apps/api/BUILD.gn
index aec7a4c858..dd3107f7 100644
--- a/chrome/browser/apps/platform_apps/api/BUILD.gn
+++ b/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//chrome/common/apps/platform_apps/api/api_sources.gni")
 import("//extensions/buildflags/buildflags.gni")
@@ -43,6 +44,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//chrome/app:generated_resources_grit",
 
     # TODO(https://crbug.com/883570): It'd be nice to have more APIs here
@@ -63,7 +65,7 @@
   public_deps =
       [ "//chrome/browser/apps/platform_apps/api/music_manager_private" ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "arc_apps_private/arc_apps_private_api.cc",
       "arc_apps_private/arc_apps_private_api.h",
diff --git a/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc
index e46b6f8..049ee513 100644
--- a/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc
+++ b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.h"
 
-#if defined(OS_CHROMEOS)
+#include "build/chromeos_buildflags.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h"
 #endif
 
@@ -12,7 +14,7 @@
 namespace api {
 
 void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ArcAppsPrivateAPI::GetFactoryInstance();
 #endif
 }
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn b/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn
index ed988b8e..2b63f283 100644
--- a/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn
+++ b/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//extensions/buildflags/buildflags.gni")
 import("//rlz/buildflags/buildflags.gni")
@@ -30,9 +31,9 @@
     libs += [ "iphlpapi.lib" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "device_id_chromeos.cc" ]
-  } else if (is_linux) {
+  } else if (is_linux || is_chromeos_lacros) {
     sources += [ "device_id_linux.cc" ]
   } else if (is_mac) {
     sources += [ "device_id_mac.cc" ]
@@ -40,7 +41,7 @@
     sources += [ "device_id_win.cc" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//chromeos/cryptohome" ]
   }
 
diff --git a/chrome/browser/apps/platform_apps/app_browsertest.cc b/chrome/browser/apps/platform_apps/app_browsertest.cc
index 36be8080..6d5735b 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest.cc
+++ b/chrome/browser/apps/platform_apps/app_browsertest.cc
@@ -18,6 +18,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
@@ -71,7 +72,7 @@
 #include "ui/display/types/display_constants.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
@@ -185,7 +186,7 @@
 
 #endif  // ENABLE_PRINT_PREVIEW
 
-#if !defined(OS_CHROMEOS) && !defined(OS_WIN)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_WIN)
 bool CopyTestDataAndGetTestFilePath(const base::FilePath& test_data_file,
                                     const base::FilePath& temp_dir,
                                     const char* filename,
@@ -198,7 +199,7 @@
   *file_path = path;
   return true;
 }
-#endif  // !defined(OS_CHROMEOS) && !defined(OS_WIN)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_WIN)
 
 class PlatformAppWithFileBrowserTest : public PlatformAppBrowserTest {
  public:
@@ -293,7 +294,7 @@
 };
 
 const char kChromiumURL[] = "http://chromium.org";
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
 #endif
 
@@ -590,7 +591,7 @@
 
 // ChromeOS does not support passing arguments on the command line, so the tests
 // that rely on this functionality are disabled.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests that launch data is sent through if the file extension matches.
 IN_PROC_BROWSER_TEST_F(PlatformAppWithFileBrowserTest,
                        LaunchFilesWithFileExtension) {
@@ -800,9 +801,9 @@
       << message_;
 }
 
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // TODO(https://crbug.com/1000234): Re-enable this test.
 #define MAYBE_OpenLink DISABLED_OpenLink
 #else
@@ -1231,7 +1232,7 @@
 
 #endif  // ENABLE_PRINT_PREVIEW
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 class PlatformAppIncognitoBrowserTest : public PlatformAppBrowserTest,
                                         public AppWindowRegistry::Observer {
@@ -1258,7 +1259,7 @@
 };
 
 // Seen to fail repeatedly on CrOS; crbug.com/774011.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_IncognitoComponentApp IncognitoComponentApp
 #else
 #define MAYBE_IncognitoComponentApp DISABLED_IncognitoComponentApp
@@ -1364,7 +1365,7 @@
   EXPECT_EQ(1, num_request_restart_calls());
 }
 
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Test that when an application is uninstalled and re-install it does not have
 // access to the previously set data.
diff --git a/chrome/browser/apps/platform_apps/app_browsertest_util.cc b/chrome/browser/apps/platform_apps/app_browsertest_util.cc
index a9c889b..a4e19989 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest_util.cc
+++ b/chrome/browser/apps/platform_apps/app_browsertest_util.cc
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -30,7 +31,7 @@
 #include "extensions/common/switches.h"
 #include "extensions/test/extension_test_message_listener.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/ash/cast_config_controller_media_router.h"
 #include "components/media_router/browser/media_routes_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -65,7 +66,7 @@
 
 void PlatformAppBrowserTest::SetUpOnMainThread() {
   ExtensionApiTest::SetUpOnMainThread();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Mock the Media Router in extension api tests. Several of the
   // PlatformAppBrowserTest suites call RunAllPendingInMessageLoop() when there
   // are mojo messages that will call back into Profile creation through the
@@ -79,7 +80,7 @@
 }
 
 void PlatformAppBrowserTest::TearDownOnMainThread() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   CastConfigControllerMediaRouter::SetMediaRouterForTest(nullptr);
 #endif
   ExtensionApiTest::TearDownOnMainThread();
diff --git a/chrome/browser/apps/platform_apps/app_browsertest_util.h b/chrome/browser/apps/platform_apps/app_browsertest_util.h
index 684c894..82e43cd 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest_util.h
+++ b/chrome/browser/apps/platform_apps/app_browsertest_util.h
@@ -11,10 +11,11 @@
 #include <string>
 
 #include "base/macros.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "extensions/browser/app_window/app_window.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/media_router/browser/test/mock_media_router.h"
 #endif
 
@@ -130,7 +131,7 @@
   NativeAppWindow* GetNativeAppWindowForAppWindow(AppWindow* window);
 
  private:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<media_router::MockMediaRouter> media_router_;
 #endif
 
diff --git a/chrome/browser/apps/platform_apps/app_window_browsertest.cc b/chrome/browser/apps/platform_apps/app_window_browsertest.cc
index 58c3d2ed..113c213 100644
--- a/chrome/browser/apps/platform_apps/app_window_browsertest.cc
+++ b/chrome/browser/apps/platform_apps/app_window_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/run_loop.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -150,7 +151,9 @@
 }
 
 // Flaky on Linux. http://crbug.com/424399.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #define MAYBE_TestMinimize DISABLED_TestMinimize
 #elif defined(OS_MAC)
 // Fails on Mac: https://crbug.com/834908
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 519b284..d1e267b 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -104,6 +104,7 @@
 #include "chrome/browser/badging/badge_manager.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h"
+#include "chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_ui.h"
 #include "chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom.h"
 #include "chrome/browser/payments/payment_credential_factory.h"
@@ -810,6 +811,9 @@
 #if !defined(OS_ANDROID)
   RegisterWebUIControllerInterfaceBinder<media::mojom::KaleidoscopeDataProvider,
                                          KaleidoscopeUI, NewTabPageUI>(map);
+  RegisterWebUIControllerInterfaceBinder<
+      media::mojom::KaleidoscopeIdentityManager, KaleidoscopeUI, NewTabPageUI>(
+      map);
 #endif  // !defined(OS_ANDROID)
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 9085205..7bb0ee1 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -895,8 +895,12 @@
     "borealis/borealis_task.h",
     "borealis/borealis_util.cc",
     "borealis/borealis_util.h",
+    "borealis/borealis_window_manager.cc",
+    "borealis/borealis_window_manager.h",
     "borealis/infra/described.h",
     "borealis/infra/expected.h",
+    "borealis/infra/state_manager.h",
+    "borealis/infra/transition.h",
     "browser_context_keyed_service_factories.cc",
     "browser_context_keyed_service_factories.h",
     "camera_detector.cc",
@@ -3379,6 +3383,8 @@
     "borealis/borealis_task_unittest.cc",
     "borealis/infra/described_unittest.cc",
     "borealis/infra/expected_unittest.cc",
+    "borealis/infra/state_manager_unittest.cc",
+    "borealis/infra/transition_unittest.cc",
     "camera_mic/vm_camera_mic_manager_unittest.cc",
     "cert_provisioning/cert_provisioning_invalidator_unittest.cc",
     "cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc",
diff --git a/chrome/browser/chromeos/borealis/borealis_service.h b/chrome/browser/chromeos/borealis/borealis_service.h
index ab4be18..9f28a9b 100644
--- a/chrome/browser/chromeos/borealis/borealis_service.h
+++ b/chrome/browser/chromeos/borealis/borealis_service.h
@@ -11,9 +11,9 @@
 
 namespace borealis {
 
-class BorealisFeatures;
-
 class BorealisAppLauncher;
+class BorealisFeatures;
+class BorealisWindowManager;
 
 // A common location for all the interdependant components of borealis.
 class BorealisService : public KeyedService {
@@ -23,9 +23,9 @@
 
   ~BorealisService() override = default;
 
-  virtual BorealisFeatures& Features() = 0;
-
   virtual BorealisAppLauncher& AppLauncher() = 0;
+  virtual BorealisFeatures& Features() = 0;
+  virtual BorealisWindowManager& WindowManager() = 0;
 };
 
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_service_impl.cc b/chrome/browser/chromeos/borealis/borealis_service_impl.cc
index 27cd1b98..f3b515e6 100644
--- a/chrome/browser/chromeos/borealis/borealis_service_impl.cc
+++ b/chrome/browser/chromeos/borealis/borealis_service_impl.cc
@@ -6,21 +6,29 @@
 
 #include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
 #include "chrome/browser/chromeos/borealis/borealis_features.h"
+#include "chrome/browser/chromeos/borealis/borealis_window_manager.h"
 #include "chrome/browser/profiles/profile.h"
 
 namespace borealis {
 
 BorealisServiceImpl::BorealisServiceImpl(Profile* profile)
-    : profile_(profile), features_(profile_), app_launcher_(profile_) {}
+    : profile_(profile),
+      app_launcher_(profile_),
+      features_(profile_),
+      window_manager_(profile_) {}
 
 BorealisServiceImpl::~BorealisServiceImpl() = default;
 
+BorealisAppLauncher& BorealisServiceImpl::AppLauncher() {
+  return app_launcher_;
+}
+
 BorealisFeatures& BorealisServiceImpl::Features() {
   return features_;
 }
 
-BorealisAppLauncher& BorealisServiceImpl::AppLauncher() {
-  return app_launcher_;
+BorealisWindowManager& BorealisServiceImpl::WindowManager() {
+  return window_manager_;
 }
 
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_service_impl.h b/chrome/browser/chromeos/borealis/borealis_service_impl.h
index eb962ae1..d8713e8 100644
--- a/chrome/browser/chromeos/borealis/borealis_service_impl.h
+++ b/chrome/browser/chromeos/borealis/borealis_service_impl.h
@@ -5,10 +5,11 @@
 #ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_SERVICE_IMPL_H_
 #define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_SERVICE_IMPL_H_
 
-#include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
 #include "chrome/browser/chromeos/borealis/borealis_service.h"
 
+#include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
 #include "chrome/browser/chromeos/borealis/borealis_features.h"
+#include "chrome/browser/chromeos/borealis/borealis_window_manager.h"
 
 namespace borealis {
 
@@ -20,13 +21,15 @@
 
  private:
   // BorealisService overrides.
-  BorealisFeatures& Features() override;
   BorealisAppLauncher& AppLauncher() override;
+  BorealisFeatures& Features() override;
+  BorealisWindowManager& WindowManager() override;
 
   Profile* const profile_;
 
-  BorealisFeatures features_;
   BorealisAppLauncher app_launcher_;
+  BorealisFeatures features_;
+  BorealisWindowManager window_manager_;
 };
 
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_window_manager.cc b/chrome/browser/chromeos/borealis/borealis_window_manager.cc
new file mode 100644
index 0000000..f7b9443
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/borealis_window_manager.cc
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/borealis/borealis_window_manager.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/chromeos/borealis/borealis_util.h"
+#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h"
+#include "components/exo/shell_surface_util.h"
+
+namespace {
+
+// Borealis windows are created with app/startup ids beginning with this.
+const char kBorealisWindowPrefix[] = "org.chromium.borealis.";
+
+// Returns an ID for this window (which is the app_id or startup_id, depending
+// on which are set. The ID string is owned by the window.
+const std::string* GetWindowId(aura::Window* window) {
+  const std::string* id = exo::GetShellApplicationId(window);
+  if (id)
+    return id;
+  return exo::GetShellStartupId(window);
+}
+
+}  // namespace
+
+namespace borealis {
+
+// static
+bool BorealisWindowManager::IsBorealisWindow(aura::Window* window) {
+  const std::string* id = GetWindowId(window);
+  if (!id)
+    return false;
+  return base::StartsWith(*id, kBorealisWindowPrefix);
+}
+
+BorealisWindowManager::BorealisWindowManager(Profile* profile)
+    : profile_(profile) {}
+
+std::string BorealisWindowManager::GetShelfAppId(aura::Window* window) {
+  if (!IsBorealisWindow(window))
+    return {};
+  // TODO(b/173977876): When we have better ways of associating apps with
+  // windows we will implement them. Until then, the mapping is identical to
+  // Crostini's so just spoof the relevant information and use theirs.
+  std::string pretend_crostini_id(*GetWindowId(window));
+  base::ReplaceFirstSubstringAfterOffset(
+      &pretend_crostini_id, 0, kBorealisWindowPrefix, "org.chromium.termina.");
+  std::string crostini_equivalent_id =
+      crostini::GetCrostiniShelfAppId(profile_, &pretend_crostini_id, nullptr);
+
+  // If crostini thinks this app is registered, then it actually is registered
+  // for borealis.
+  if (!crostini::IsUnmatchedCrostiniShelfAppId(crostini_equivalent_id))
+    return crostini_equivalent_id;
+
+  // The app has no registration, it is anonymous.
+  return crostini_equivalent_id;
+}
+
+}  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_window_manager.h b/chrome/browser/chromeos/borealis/borealis_window_manager.h
new file mode 100644
index 0000000..99dba439
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/borealis_window_manager.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_WINDOW_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_WINDOW_MANAGER_H_
+
+#include <string>
+
+class Profile;
+
+namespace aura {
+class Window;
+}
+
+namespace borealis {
+
+class BorealisWindowManager {
+ public:
+  // Returns true if this window belongs to a borealis VM (based on its app_id
+  // and startup_id).
+  static bool IsBorealisWindow(aura::Window* window);
+
+  explicit BorealisWindowManager(Profile* profile);
+
+  std::string GetShelfAppId(aura::Window* window);
+
+ private:
+  Profile* const profile_;
+};
+
+}  // namespace borealis
+
+#endif  // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_WINDOW_MANAGER_H_
diff --git a/chrome/browser/chromeos/borealis/infra/expected.h b/chrome/browser/chromeos/borealis/infra/expected.h
index 4fe6544..f19ab407 100644
--- a/chrome/browser/chromeos/borealis/infra/expected.h
+++ b/chrome/browser/chromeos/borealis/infra/expected.h
@@ -13,8 +13,8 @@
 // TODO(b/172501195): Make these available outside namespace borealis.
 namespace borealis {
 
-// When signalling results that can succeed or fail, an Expected is used to
-// fomalise those two options either with a |T|, indicating success, or an |E|
+// When signaling results that can succeed or fail, an Expected is used to
+// formalize those two options either with a |T|, indicating success, or an |E|
 // which indicates failure.
 //
 // This class is a non-drop-in-replacement for the std::expected, as that RFC is
@@ -32,18 +32,17 @@
 
   // TODO(b/172501195): This implementation is only partial, either complete it
   // or replace it with the standard. Until then |T| and |E| should probably be
-  // copyable.
-  static_assert(std::is_copy_constructible<T>::value,
-                "Expected's value type must be copy-constructible");
-  static_assert(std::is_copy_assignable<T>::value,
-                "Expected's value type must be copy-assignable");
+  // movable and copy-able respectively.
+  static_assert(std::is_move_constructible<T>::value,
+                "Expected's value type must be move-constructible");
   static_assert(std::is_copy_constructible<E>::value,
                 "Expected's error type must be copy-constructible");
   static_assert(std::is_copy_assignable<E>::value,
                 "Expected's error type must be copy-assignable");
 
   // Construct an object with the expected type.
-  explicit Expected(T value) : storage_(value) {}
+  template <class TT>
+  explicit Expected(TT&& value) : storage_(std::forward<T>(value)) {}
 
   // Construct an object with the error type.
   static Expected<T, E> Unexpected(E error) { return Expected(error); }
@@ -58,11 +57,11 @@
 
   // Unsafe access to the underlying value. Use only if you know |this| is in
   // the requested state.
-  T Value() { return absl::get<T>(storage_); }
+  T& Value() { return absl::get<T>(storage_); }
 
   // Unsafe access to the underlying error. Use only if you know |this| is in
   // the requested state.
-  E Error() { return absl::get<E>(storage_); }
+  E& Error() { return absl::get<E>(storage_); }
 
   // Safe access to the underlying value, or nullptr;
   T* MaybeValue() { return absl::get_if<T>(&storage_); }
diff --git a/chrome/browser/chromeos/borealis/infra/state_manager.h b/chrome/browser/chromeos/borealis/infra/state_manager.h
new file mode 100644
index 0000000..719708f2
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/infra/state_manager.h
@@ -0,0 +1,182 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_STATE_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_STATE_MANAGER_H_
+
+#include <memory>
+
+#include "base/callback_list.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "chrome/browser/chromeos/borealis/infra/expected.h"
+#include "chrome/browser/chromeos/borealis/infra/transition.h"
+
+namespace borealis {
+
+// A tool for organizing callbacks that depend on the system being in a certain
+// state, represented by an object of type |State|. Clients of the state manager
+// can make requests that the system transition between the "On" and "Off"
+// states, which relate to the presence or absence of the |State| instance.
+//
+// A request to transition the system comes in the form of a callback, which
+// will be invoked asynchronously when the system is in the requested state. The
+// system will transition based on the most recent callback.
+//
+// The state manager can itself be in one of 4 phases:
+//
+//        [Off] <-----> {Transitioning On}
+//          ^                   |
+//          |                   v
+//  {Transitioning Off} <------ [On]
+//
+// These phases relate to |State| instances as well as the enqueueing of
+// callbacks:
+//  - |State| is nonexistent while "Off", is immediately created at the start of
+//    "Transitioning On", exists while "On", and is immediately deleted at the
+//    start of "Transitioning Off"
+//  - When the system is "Off", a callback to turn the system "On" will be
+//    enqueued, and move the manger to "Transitioning On". Additional requests
+//    will be enqueued until the system is "On", when all queued callbacks will
+//    be invoked (as will new requests). Vice-versa is true for turning the
+//    system "Off" when in the "On" state.
+//  - When a system is "Transitioning On", all requests to turn the system "Off"
+//    will be rejected, until the system is "On", then they will be enqueued.
+//    Vice-versa is true for turning the system "On" in the "Transitioning Off"
+//    state.
+//
+// A system can only fail to turn "On", in which case the |State| instance will
+// be deleted and the failure |OnError| will be reported to callbacks. A system
+// can always transition to "Off" but it may do so uncleanly, which will result
+// in an |OffError| being reported.
+template <typename State, typename OnError, typename OffError>
+class BorealisStateManager {
+ public:
+  // An empty state which is a marker that the state manager is off. This state
+  // holds no data,
+  struct OffState {};
+
+  // Convenience typedefs.
+  using OnTransition = Transition<OffState, State, OnError>;
+  using OffTransition = Transition<State, OffState, OffError>;
+  using WhenOn = void(Expected<State*, OnError>);
+  using WhenOff = void(base::Optional<OffError>);
+
+  // Create the state object, turning the state to "on". The |callback| will be
+  // invoked on completion with the result.
+  void TurnOn(base::OnceCallback<WhenOn> callback) {
+    switch (GetPhase()) {
+      case Phase::kOff:
+        on_transition_ = GetOnTransition();
+        on_transition_->Begin(std::make_unique<OffState>(),
+                              base::BindOnce(&BorealisStateManager::CompleteOn,
+                                             weak_ptr_factory_.GetWeakPtr()));
+        pending_on_callbacks_.AddUnsafe(std::move(callback));
+        break;
+      case Phase::kTransitioningOn:
+        pending_on_callbacks_.AddUnsafe(std::move(callback));
+        break;
+      case Phase::kOn:
+        std::move(callback).Run(Expected<State*, OnError>(instance_.get()));
+        break;
+      case Phase::kTransitioningOff:
+        std::move(callback).Run(Unexpected<State*>(GetIsTurningOffError()));
+        break;
+    }
+  }
+
+  // Remove the state object, turning the state to "off". The |callback| will be
+  // invoked on completion with an error (or not, if successful).
+  void TurnOff(base::OnceCallback<WhenOff> callback) {
+    switch (GetPhase()) {
+      case Phase::kOff:
+        std::move(callback).Run(base::nullopt);
+        break;
+      case Phase::kTransitioningOn:
+        std::move(callback).Run(GetIsTurningOnError());
+        break;
+      case Phase::kOn:
+        off_transition_ = GetOffTransition();
+        off_transition_->Begin(
+            std::move(instance_),
+            base::BindOnce(&BorealisStateManager::CompleteOff,
+                           weak_ptr_factory_.GetWeakPtr()));
+        pending_off_callbacks_.AddUnsafe(std::move(callback));
+        break;
+      case Phase::kTransitioningOff:
+        pending_off_callbacks_.AddUnsafe(std::move(callback));
+        break;
+    }
+  }
+
+ protected:
+  // Factory method to build the transition needed to turn this state manager
+  // on.
+  virtual std::unique_ptr<OnTransition> GetOnTransition() = 0;
+
+  // Factory method to build the transition needed to turn this state manager
+  // off.
+  virtual std::unique_ptr<OffTransition> GetOffTransition() = 0;
+
+  // Factory method to build the error which was the result of rejecting a
+  // request to turn the state on.
+  virtual OnError GetIsTurningOffError() = 0;
+
+  // Factory method to build the error which was the result of rejecting a
+  // request to turn the state off.
+  virtual OffError GetIsTurningOnError() = 0;
+
+ private:
+  // The phases of managing a state object.
+  enum class Phase {
+    kOff,
+    kTransitioningOn,
+    kOn,
+    kTransitioningOff,
+  };
+
+  // Returns the current phase of the state manager.
+  Phase GetPhase() const {
+    if (instance_) {
+      return Phase::kOn;
+    } else if (on_transition_) {
+      DCHECK(!off_transition_);
+      return Phase::kTransitioningOn;
+    } else if (off_transition_) {
+      return Phase::kTransitioningOff;
+    } else {
+      return Phase::kOff;
+    }
+  }
+
+  void CompleteOn(typename OnTransition::Result on_result) {
+    if (on_result) {
+      std::swap(instance_, on_result.Value());
+      on_transition_.reset();
+      pending_on_callbacks_.Notify(Expected<State*, OnError>(instance_.get()));
+    } else {
+      on_transition_.reset();
+      pending_on_callbacks_.Notify(Unexpected<State*>(on_result.Error()));
+    }
+  }
+
+  void CompleteOff(typename OffTransition::Result off_result) {
+    off_transition_.reset();
+    pending_off_callbacks_.Notify(
+        off_result ? base::nullopt
+                   : base::Optional<OffError>(off_result.Error()));
+  }
+
+  std::unique_ptr<State> instance_;
+  std::unique_ptr<OnTransition> on_transition_;
+  std::unique_ptr<OffTransition> off_transition_;
+  base::OnceCallbackList<WhenOn> pending_on_callbacks_;
+  base::OnceCallbackList<WhenOff> pending_off_callbacks_;
+  base::WeakPtrFactory<BorealisStateManager<State, OnError, OffError>>
+      weak_ptr_factory_{this};
+};
+
+}  // namespace borealis
+
+#endif  // CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_STATE_MANAGER_H_
diff --git a/chrome/browser/chromeos/borealis/infra/state_manager_unittest.cc b/chrome/browser/chromeos/borealis/infra/state_manager_unittest.cc
new file mode 100644
index 0000000..857eb43e
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/infra/state_manager_unittest.cc
@@ -0,0 +1,228 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/borealis/infra/state_manager.h"
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/optional.h"
+#include "base/test/task_environment.h"
+#include "chrome/browser/chromeos/borealis/infra/expected.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace borealis {
+namespace {
+
+template <typename F>
+class CallbackFactory : public testing::StrictMock<testing::MockFunction<F>> {
+ public:
+  base::OnceCallback<F> GetOnce() {
+    return base::BindOnce(&CallbackFactory<F>::Call, base::Unretained(this));
+  }
+};
+
+struct Foo {
+  std::string msg;
+};
+struct Bar {
+  std::string msg;
+};
+struct Baz {
+  std::string msg;
+};
+
+class MockStateManager : public BorealisStateManager<Foo, Bar, Baz> {
+ public:
+  MOCK_METHOD(std::unique_ptr<OnTransition>, GetOnTransition, (), ());
+  MOCK_METHOD(std::unique_ptr<OffTransition>, GetOffTransition, (), ());
+  MOCK_METHOD(Bar, GetIsTurningOffError, (), ());
+  MOCK_METHOD(Baz, GetIsTurningOnError, (), ());
+};
+
+class NonCompletingOnTransition : public MockStateManager::OnTransition {
+  void Start(std::unique_ptr<MockStateManager::OffState> in) override {}
+};
+
+class SucceedingOnTransition : public MockStateManager::OnTransition {
+  void Start(std::unique_ptr<MockStateManager::OffState> in) override {
+    Succeed(std::make_unique<Foo>());
+  }
+};
+
+class FailingOnTransition : public MockStateManager::OnTransition {
+  void Start(std::unique_ptr<MockStateManager::OffState> in) override {
+    Fail(Bar{.msg = "failure turning on"});
+  }
+};
+
+class NonCompletingOffTransition : public MockStateManager::OffTransition {
+  void Start(std::unique_ptr<Foo> in) override {}
+};
+
+class SucceedingOffTransition : public MockStateManager::OffTransition {
+  void Start(std::unique_ptr<Foo> in) override { Succeed(nullptr); }
+};
+
+class FailingOffTransition : public MockStateManager::OffTransition {
+  void Start(std::unique_ptr<Foo> in) override {
+    Fail(Baz{.msg = "failure turning off"});
+  }
+};
+
+TEST(BorealisStateManagerTest, DefaultStateIsOff) {
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOff> on_callback_handler;
+  // State managers are created in the "Off" state, so we don't need to
+  // transition there.
+  EXPECT_CALL(state_manager, GetOffTransition).Times(0);
+  EXPECT_CALL(on_callback_handler, Call(testing::Eq(base::nullopt)));
+  state_manager.TurnOff(on_callback_handler.GetOnce());
+}
+
+TEST(BorealisStateManagerTest, CanBeTurnedOnAndOff) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOn> on_callback_handler;
+  CallbackFactory<MockStateManager::WhenOff> off_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<SucceedingOnTransition>();
+  }));
+  EXPECT_CALL(state_manager, GetOffTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<SucceedingOffTransition>();
+  }));
+  EXPECT_CALL(on_callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke(
+          [](Expected<Foo*, Bar> result) { EXPECT_TRUE(result); }));
+  EXPECT_CALL(off_callback_handler, Call(testing::Eq(base::nullopt)));
+
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+  state_manager.TurnOff(off_callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+}
+
+TEST(BorealisStateManagerTest, CanHandleMultipleCallbacks) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOn> on_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<SucceedingOnTransition>();
+  }));
+
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+
+  // The above two callbacks will not be run until the sequence gets a chance to
+  // execute. We assure this by making the expectations after them.
+  EXPECT_CALL(on_callback_handler, Call(testing::_))
+      .Times(3)
+      .WillRepeatedly(testing::Invoke(
+          [](Expected<Foo*, Bar> result) { EXPECT_TRUE(result); }));
+
+  // The two callbacks will have a chance to run now.
+  task_environment.RunUntilIdle();
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+}
+
+TEST(BorealisStateManagerTest, TurnOffRejectedWhileTurningOn) {
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOff> off_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<NonCompletingOnTransition>();
+  }));
+  EXPECT_CALL(state_manager, GetIsTurningOnError)
+      .WillOnce(testing::Return(Baz{.msg = "rejected"}));
+  EXPECT_CALL(off_callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke([](base::Optional<Baz> err) {
+        ASSERT_TRUE(err.has_value());
+        EXPECT_EQ(err->msg, "rejected");
+      }));
+
+  state_manager.TurnOn(base::DoNothing());
+  state_manager.TurnOff(off_callback_handler.GetOnce());
+}
+
+TEST(BorealisStateManagerTest, TurnOnRejectedWhileTurningOff) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOn> on_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<SucceedingOnTransition>();
+  }));
+  EXPECT_CALL(state_manager, GetOffTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<NonCompletingOffTransition>();
+  }));
+  EXPECT_CALL(state_manager, GetIsTurningOffError)
+      .WillOnce(testing::Return(Bar{.msg = "blocked"}));
+  EXPECT_CALL(on_callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke([](Expected<Foo*, Bar> result) {
+        EXPECT_TRUE(result.Unexpected());
+        EXPECT_EQ(result.Error().msg, "blocked");
+      }));
+
+  state_manager.TurnOn(base::DoNothing());
+  task_environment.RunUntilIdle();
+  state_manager.TurnOff(base::DoNothing());
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+}
+
+TEST(BorealisStateManagerTest, FailureToTurnOnProducesAnErrorAndResultsInOff) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOn> on_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<FailingOnTransition>();
+  }));
+  EXPECT_CALL(on_callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke(
+          [](Expected<Foo*, Bar> result) { EXPECT_FALSE(result); }));
+
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+
+  // Additional call to turn off requires no transition, because the state is
+  // off.
+  CallbackFactory<MockStateManager::WhenOff> off_callback_handler;
+  EXPECT_CALL(off_callback_handler, Call(testing::Eq(base::nullopt)));
+  state_manager.TurnOff(off_callback_handler.GetOnce());
+}
+
+TEST(BorealisStateManagerTest, FailureToTurnOffProducesErrorButDoesTurnOff) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  testing::StrictMock<MockStateManager> state_manager;
+  CallbackFactory<MockStateManager::WhenOn> on_callback_handler;
+  CallbackFactory<MockStateManager::WhenOff> off_callback_handler;
+
+  EXPECT_CALL(state_manager, GetOnTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<SucceedingOnTransition>();
+  }));
+  EXPECT_CALL(state_manager, GetOffTransition).WillOnce(testing::Invoke([]() {
+    return std::make_unique<FailingOffTransition>();
+  }));
+  EXPECT_CALL(on_callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke(
+          [](Expected<Foo*, Bar> result) { EXPECT_TRUE(result); }));
+  EXPECT_CALL(off_callback_handler,
+              Call(testing::Not(testing::Eq(base::nullopt))));
+
+  state_manager.TurnOn(on_callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+  state_manager.TurnOff(off_callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+
+  // Additional call to turn off requires no transition, because the state is
+  // off.
+  EXPECT_CALL(off_callback_handler, Call(testing::Eq(base::nullopt)));
+  state_manager.TurnOff(off_callback_handler.GetOnce());
+}
+
+}  // namespace
+}  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/infra/transition.h b/chrome/browser/chromeos/borealis/infra/transition.h
new file mode 100644
index 0000000..5cb21fb
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/infra/transition.h
@@ -0,0 +1,86 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_TRANSITION_H_
+#define CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_TRANSITION_H_
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "chrome/browser/chromeos/borealis/infra/expected.h"
+
+// TODO(b/172501195): Make these available outside namespace borealis.
+namespace borealis {
+
+// A transition object is used to represent a transformation of a start state
+// |S| into a terminating state |T|. The transition can fail, in which case the
+// result is an error state |E|.
+//
+// The transition centers around a state object of type |S|, which will become
+// an instance of |T| if the transition succeeds, and an error |E| if it does
+// not.
+//
+// The transition itself is in one of three modes:
+//  - A "pending" transition has been created and is waiting for control of the
+//    |S| instance to begin the transition.
+//  - A "working" transition has control of the |S| object, and is transforming
+//    it into |T|. There is no guarantee at this point about the existence of an
+//    |S| or |T| instance.
+//  - A "final" transition has completed, and either succeeded (in which case
+//    a |T| instance exists) or failed (in which case |T| does not exist and an
+//    |E| error has been generated.
+//
+// Once the transition is "final" no further work is possible and the transition
+// can be deleted.
+template <typename S, typename T, typename E>
+class Transition {
+ public:
+  using Result = Expected<std::unique_ptr<T>, E>;
+
+  using OnCompleteSignature = void(Result);
+
+  using OnCompleteCallback = base::OnceCallback<OnCompleteSignature>;
+
+  Transition() = default;
+  virtual ~Transition() = default;
+
+  // Begin the transition, marking this transition as "working" and giving
+  // ownership of the |S| object to the transition.
+  void Begin(std::unique_ptr<S> start_instance, OnCompleteCallback callback) {
+    callback_ = std::move(callback);
+    Start(std::move(start_instance));
+  }
+
+ protected:
+  // Override this method to define the work that this transition performs. As
+  // soon as this function is entered, the transition is "working", until you
+  // call Succeed() or Fail(), which should be the last things you call.
+  virtual void Start(std::unique_ptr<S> start_instance) = 0;
+
+  // Called when the transition has completed successfully. This should be the
+  // last thing you do.
+  void Succeed(std::unique_ptr<T> terminating_instance) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback_),
+                                  Result(std::move(terminating_instance))));
+  }
+
+  // Called when the transition has completed unsuccessfully. This should only
+  // be called at the very end of the failing transition (including cleanup if
+  // needed).
+  void Fail(E error) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback_),
+                                  Result::Unexpected(std::move(error))));
+  }
+
+ private:
+  OnCompleteCallback callback_;
+};
+
+}  // namespace borealis
+
+#endif  // CHROME_BROWSER_CHROMEOS_BOREALIS_INFRA_TRANSITION_H_
diff --git a/chrome/browser/chromeos/borealis/infra/transition_unittest.cc b/chrome/browser/chromeos/borealis/infra/transition_unittest.cc
new file mode 100644
index 0000000..f6a72be
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/infra/transition_unittest.cc
@@ -0,0 +1,69 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/borealis/infra/transition.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace borealis {
+namespace {
+
+template <typename F>
+class CallbackFactory : public testing::StrictMock<testing::MockFunction<F>> {
+ public:
+  base::OnceCallback<F> GetOnce() {
+    return base::BindOnce(&CallbackFactory<F>::Call, base::Unretained(this));
+  }
+};
+
+class ParseIntTransition : public Transition<std::string, int, bool> {
+  void Start(std::unique_ptr<std::string> in) override {
+    int val;
+    if (base::StringToInt(*in, &val)) {
+      Succeed(std::make_unique<int>(val));
+    } else {
+      Fail(false);
+    }
+  }
+};
+
+TEST(TransitionTest, TransitionCanTransformInputToOutput) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  ParseIntTransition transition;
+  CallbackFactory<ParseIntTransition::OnCompleteSignature> callback_handler;
+
+  EXPECT_CALL(callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke([](ParseIntTransition::Result result) {
+        ASSERT_TRUE(result);
+        EXPECT_EQ(*result.Value(), 12345);
+      }));
+
+  transition.Begin(std::make_unique<std::string>("12345"),
+                   callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+}
+
+TEST(TransitionTest, TransitionCanFail) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  ParseIntTransition transition;
+  CallbackFactory<ParseIntTransition::OnCompleteSignature> callback_handler;
+
+  EXPECT_CALL(callback_handler, Call(testing::_))
+      .WillOnce(testing::Invoke([](ParseIntTransition::Result result) {
+        EXPECT_TRUE(result.Unexpected());
+      }));
+
+  transition.Begin(std::make_unique<std::string>("not a number"),
+                   callback_handler.GetOnce());
+  task_environment.RunUntilIdle();
+}
+
+}  // namespace
+}  // namespace borealis
diff --git a/chrome/browser/chromeos/exo/chrome_file_helper.cc b/chrome/browser/chromeos/exo/chrome_file_helper.cc
index e027d04..c9c1ffd 100644
--- a/chrome/browser/chromeos/exo/chrome_file_helper.cc
+++ b/chrome/browser/chromeos/exo/chrome_file_helper.cc
@@ -18,6 +18,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
+#include "chrome/browser/chromeos/extensions/file_manager/event_router_factory.h"
 #include "chrome/browser/chromeos/file_manager/app_id.h"
 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/file_manager/path_util.h"
@@ -216,13 +218,25 @@
   std::string joined = base::JoinString(lines_to_send, kUriListSeparator);
   auto data = base::RefCountedString::TakeString(&joined);
   if (!paths_to_share.empty()) {
-    share_path->SharePaths(
-        vm_name, std::move(paths_to_share),
-        /*persist=*/false,
-        base::BindOnce(&SendAfterShare, std::move(callback), std::move(data)));
-  } else {
-    std::move(callback).Run(std::move(data));
+    if (!is_plugin_vm) {
+      share_path->SharePaths(
+          vm_name, std::move(paths_to_share),
+          /*persist=*/false,
+          base::BindOnce(&SendAfterShare, std::move(callback),
+                         std::move(data)));
+      return;
+    }
+
+    // Show FilesApp move-to-windows-files dialog when Plugin VM is not shared.
+    if (auto* event_router =
+            file_manager::EventRouterFactory::GetForProfile(primary_profile)) {
+      event_router->DropFailedPluginVmDirectoryNotShared();
+    }
+    std::string empty;
+    data = base::RefCountedString::TakeString(&empty);
   }
+
+  std::move(callback).Run(std::move(data));
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/exo/chrome_file_helper_unittest.cc b/chrome/browser/chromeos/exo/chrome_file_helper_unittest.cc
index eb34429c..b0cb696 100644
--- a/chrome/browser/chromeos/exo/chrome_file_helper_unittest.cc
+++ b/chrome/browser/chromeos/exo/chrome_file_helper_unittest.cc
@@ -212,6 +212,10 @@
   ChromeFileHelper file_helper;
   ui::FileInfo file1(myfiles_dir_.Append("file1"), base::FilePath());
   ui::FileInfo file2(myfiles_dir_.Append("file2"), base::FilePath());
+  auto* guest_os_share_path =
+      guest_os::GuestOsSharePath::GetForProfile(profile());
+  guest_os_share_path->RegisterSharedPath(plugin_vm::kPluginVmName,
+                                          myfiles_dir_);
 
   // Arc should convert path to UTF16 URL.
   std::string data;
@@ -286,7 +290,7 @@
   EXPECT_EQ("", data);
 }
 
-TEST_F(ChromeFileHelperTest, SendFileInfoSharePaths) {
+TEST_F(ChromeFileHelperTest, SendFileInfoSharePathsCrostini) {
   ChromeFileHelper file_helper;
 
   // A path which is already shared should not be shared again.
@@ -313,6 +317,19 @@
   EXPECT_TRUE(fake_seneschal_client_->share_path_called());
 }
 
+TEST_F(ChromeFileHelperTest, SendFileInfoSharePathsPluginVm) {
+  ChromeFileHelper file_helper;
+
+  // Plugin VM should send empty data and not share path if not already shared.
+  ui::FileInfo file(myfiles_dir_.Append("file"), base::FilePath());
+  std::string data;
+  file_helper.SendFileInfo(plugin_vm_window_, {file},
+                           base::BindOnce(&Capture, &data));
+  task_environment_.RunUntilIdle();
+  EXPECT_EQ("", data);
+  EXPECT_FALSE(fake_seneschal_client_->share_path_called());
+}
+
 TEST_F(ChromeFileHelperTest, HasUrlsInPickle) {
   ChromeFileHelper file_helper;
 
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc b/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
index 3312f2a9..554607a 100644
--- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
@@ -97,7 +97,8 @@
 
 TEST_F(DocumentScanScanFunctionTest, Success) {
   GetLorgnetteScannerManager()->SetGetScannerNamesResponse({kTestScannerName});
-  GetLorgnetteScannerManager()->SetScanResponse("PrettyPicture");
+  const std::vector<std::string> scan_data = {"PrettyPicture"};
+  GetLorgnetteScannerManager()->SetScanResponse(scan_data);
   std::unique_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
       function_.get(), "[{\"mimeTypes\": [\"image/png\"]}]"));
   ASSERT_NE(nullptr, result.get());
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index f9550a9..95124d5 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
 #include "chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
@@ -953,6 +954,21 @@
       file_manager_private::OnDriveConnectionStatusChanged::Create());
 }
 
+void EventRouter::DropFailedPluginVmDirectoryNotShared() {
+  for (const auto& extension_id : GetEventListenerExtensionIds(
+           profile_, file_manager_private::OnCrostiniChanged::kEventName)) {
+    file_manager_private::CrostiniEvent event;
+    event.vm_name = plugin_vm::kPluginVmName;
+    event.event_type = file_manager_private::
+        CROSTINI_EVENT_TYPE_DROP_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED;
+    DispatchEventToExtension(
+        profile_, extension_id,
+        extensions::events::FILE_MANAGER_PRIVATE_ON_CROSTINI_CHANGED,
+        file_manager_private::OnCrostiniChanged::kEventName,
+        file_manager_private::OnCrostiniChanged::Create(event));
+  }
+}
+
 base::WeakPtr<EventRouter> EventRouter::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index 3ef8b04..ac8e7fe 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -158,6 +158,10 @@
   void OnUnshare(const std::string& vm_name,
                  const base::FilePath& path) override;
 
+  // Notifies FilesApp that file drop to Plugin VM was not in a shared directory
+  // and failed FilesApp will show the "Move to Windows files" dialog.
+  void DropFailedPluginVmDirectoryNotShared();
+
   // Returns a weak pointer for the event router.
   base::WeakPtr<EventRouter> GetWeakPtr();
 
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index e72b00fc..341589a5 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -966,7 +966,8 @@
                       TestCase("enableDisableCrostini"),
                       TestCase("sharePathWithCrostini"),
                       TestCase("pluginVmDirectoryNotSharedErrorDialog"),
-                      TestCase("pluginVmFileOnExternalDriveErrorDialog")));
+                      TestCase("pluginVmFileOnExternalDriveErrorDialog"),
+                      TestCase("pluginVmFileDropFailErrorDialog")));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
     MyFiles, /* my_files.js */
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index a6963a6..4d7325fa 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -40,6 +40,8 @@
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/drive/drivefs_test_support.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
+#include "chrome/browser/chromeos/extensions/file_manager/event_router_factory.h"
 #include "chrome/browser/chromeos/file_manager/app_id.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_test_util.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h"
@@ -2032,6 +2034,12 @@
     return;
   }
 
+  if (name == "isDevtoolsCoverageActive") {
+    LOG(INFO) << "isDevtoolsCoverageActive: " << devtools_code_coverage_;
+    *output = devtools_code_coverage_ ? "true" : "false";
+    return;
+  }
+
   if (name == "launchAppOnDrive") {
     auto* integration_service =
         drive::DriveIntegrationServiceFactory::FindForProfile(profile());
@@ -2676,6 +2684,11 @@
     return;
   }
 
+  if (name == "onDropFailedPluginVmDirectoryNotShared") {
+    EventRouterFactory::GetForProfile(profile())
+        ->DropFailedPluginVmDirectoryNotShared();
+    return;
+  }
   FAIL() << "Unknown test message: " << name;
 }
 
diff --git a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
index b191e40..43d2e69 100644
--- a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
@@ -135,9 +135,7 @@
     case plugin_vm::LaunchPluginVmAppResult::SUCCESS:
       return fmp::TASK_RESULT_MESSAGE_SENT;
     case plugin_vm::LaunchPluginVmAppResult::FAILED_DIRECTORY_NOT_SHARED:
-      return fmp::TASK_RESULT_FAILED_PLUGIN_VM_TASK_DIRECTORY_NOT_SHARED;
-    case plugin_vm::LaunchPluginVmAppResult::FAILED_FILE_ON_EXTERNAL_DRIVE:
-      return fmp::TASK_RESULT_FAILED_PLUGIN_VM_TASK_EXTERNAL_DRIVE;
+      return fmp::TASK_RESULT_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED;
     case plugin_vm::LaunchPluginVmAppResult::FAILED:
       return fmp::TASK_RESULT_FAILED;
   }
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index dca9e6d2..51b1ebb 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -257,8 +257,6 @@
                const content::NotificationDetails& details) override;
 
  private:
-  friend class InputMethodManagerImplTest;
-
   // CandidateWindowController::Observer overrides:
   void CandidateClicked(int index) override;
   void CandidateWindowOpened() override;
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index 5e68641..d10b1b1 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -132,19 +132,14 @@
 
 class InputMethodManagerImplTest :  public BrowserWithTestWindowTest {
  public:
-  InputMethodManagerImplTest()
-      : delegate_(nullptr),
-        candidate_window_controller_(nullptr),
-        keyboard_(nullptr) {}
-
+  InputMethodManagerImplTest() = default;
   ~InputMethodManagerImplTest() override = default;
 
   void SetUp() override {
     ui::InitializeInputMethodForTesting();
 
-    delegate_ = new FakeInputMethodDelegate();
-    manager_.reset(new InputMethodManagerImpl(
-        std::unique_ptr<InputMethodDelegate>(delegate_), false));
+    manager_ = std::make_unique<InputMethodManagerImpl>(
+        std::make_unique<FakeInputMethodDelegate>(), false);
     manager_->GetInputMethodUtil()->UpdateHardwareLayoutCache();
     candidate_window_controller_ = new MockCandidateWindowController;
     manager_->SetCandidateWindowControllerForTesting(
@@ -171,28 +166,16 @@
     chrome_keyboard_controller_client_test_helper_.reset();
 
     BrowserWithTestWindowTest::TearDown();
-
     ui::ShutdownInputMethodForTesting();
 
-    delegate_ = nullptr;
     candidate_window_controller_ = nullptr;
     keyboard_ = nullptr;
     manager_.reset();
   }
 
-  scoped_refptr<InputMethodManagerImpl::StateImpl> GetActiveIMEState() {
-    return scoped_refptr<InputMethodManagerImpl::StateImpl>(
-        manager_->state_.get());
-  }
-
  protected:
   // Helper function to initialize component extension stuff for testing.
   void InitComponentExtension() {
-    mock_delegate_ = new MockComponentExtensionIMEManagerDelegate();
-    mock_delegate_->set_ime_list(ime_list_);
-    std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate(
-        mock_delegate_);
-
     // CreateNewState(nullptr) returns state with non-empty
     // current_input_method. So SetState() triggers ChangeInputMethod().
     InputMethodDescriptors descriptors;
@@ -206,10 +189,11 @@
                                    descriptors, mock_engine_handler_.get());
     manager_->SetState(state);
 
-    std::vector<std::string> layouts;
-    layouts.emplace_back("us");
-    std::vector<std::string> languages;
-    languages.emplace_back("en-US");
+    MockComponentExtensionIMEManagerDelegate* mock_delegate =
+        new MockComponentExtensionIMEManagerDelegate();
+    mock_delegate->set_ime_list(ime_list_);
+    std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate(
+        mock_delegate);
 
     // Note, for production, these SetEngineHandler are called when
     // IMEEngineHandlerInterface is initialized via
@@ -217,6 +201,7 @@
     manager_->InitializeComponentExtensionForTesting(std::move(delegate));
   }
 
+ private:
   void InitImeList() {
     ime_list_.clear();
 
@@ -361,14 +346,13 @@
     ime_list_.push_back(ext2);
   }
 
+ protected:
   std::unique_ptr<ChromeKeyboardControllerClientTestHelper>
       chrome_keyboard_controller_client_test_helper_;
   std::unique_ptr<InputMethodManagerImpl> manager_;
-  FakeInputMethodDelegate* delegate_;
-  MockCandidateWindowController* candidate_window_controller_;
+  MockCandidateWindowController* candidate_window_controller_ = nullptr;
   std::unique_ptr<MockInputMethodEngine> mock_engine_handler_;
-  FakeImeKeyboard* keyboard_;
-  MockComponentExtensionIMEManagerDelegate* mock_delegate_;
+  FakeImeKeyboard* keyboard_ = nullptr;
   std::vector<ComponentExtensionIME> ime_list_;
   ui::ime::InputMethodMenuManager* menu_manager_;
 
@@ -1232,8 +1216,7 @@
   manager_->RemoveObserver(&observer);
 }
 
-TEST_F(InputMethodManagerImplTest,
-       ChangeInputMethod_ComponenteExtensionOneIME) {
+TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionOneIME) {
   InitComponentExtension();
   const std::string ext_id = extension_ime_util::GetComponentInputMethodID(
       ime_list_[1].id,
@@ -1246,8 +1229,7 @@
             manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
 }
 
-TEST_F(InputMethodManagerImplTest,
-       ChangeInputMethod_ComponenteExtensionTwoIME) {
+TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionTwoIME) {
   InitComponentExtension();
   const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID(
       ime_list_[1].id,
@@ -1306,13 +1288,13 @@
 
   MockInputMethodEngine engine;
   std::vector<std::string> enabled_imes = {ime_id};
-  GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
-  GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, descriptors,
-                                               &engine);
-  GetActiveIMEState()->ChangeInputMethod(ime_id, false);
+  manager_->GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
+  manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1,
+                                                         descriptors, &engine);
+  manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false);
 
-  GetActiveIMEState()->EnableInputView();
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  manager_->GetActiveIMEState()->EnableInputView();
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(inputview_url.spec()));
 
   // Override the keyboard url ref with 'emoji'.
@@ -1321,7 +1303,7 @@
       "inputview.html#id=us.compact.qwerty.emoji&language=en-US&passwordLayout="
       "us.compact.qwerty&name=keyboard_us");
   manager_->OverrideKeyboardKeyset(chromeos::input_method::ImeKeyset::kEmoji);
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(overridden_url_emoji.spec()));
 
   // Override the keyboard url ref with 'hwt'.
@@ -1331,7 +1313,7 @@
       "us.compact.qwerty&name=keyboard_us");
   manager_->OverrideKeyboardKeyset(
       chromeos::input_method::ImeKeyset::kHandwriting);
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(overridden_url_hwt.spec()));
 
   // Override the keyboard url ref with 'voice'.
@@ -1340,7 +1322,7 @@
       "inputview.html#id=us.compact.qwerty.voice&language=en-US"
       "&passwordLayout=us.compact.qwerty&name=keyboard_us");
   manager_->OverrideKeyboardKeyset(chromeos::input_method::ImeKeyset::kVoice);
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(overridden_url_voice.spec()));
 }
 
@@ -1358,14 +1340,14 @@
 
   MockInputMethodEngine engine;
   std::vector<std::string> enabled_imes = {ime_id};
-  GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
-  GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, descriptors,
-                                               &engine);
-  GetActiveIMEState()->ChangeInputMethod(ime_id, false);
-  GetActiveIMEState()->EnableInputView();
+  manager_->GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
+  manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1,
+                                                         descriptors, &engine);
+  manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false);
+  manager_->GetActiveIMEState()->EnableInputView();
 
   manager_->OverrideKeyboardKeyset(chromeos::input_method::ImeKeyset::kEmoji);
-  EXPECT_EQ(default_url, GetActiveIMEState()->GetInputViewUrl());
+  EXPECT_EQ(default_url, manager_->GetActiveIMEState()->GetInputViewUrl());
 }
 
 TEST_F(InputMethodManagerImplTest, DoesNotResetInputViewUrlWhenOverridden) {
@@ -1386,11 +1368,11 @@
 
   MockInputMethodEngine engine;
   std::vector<std::string> enabled_imes = {ime_id};
-  GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
-  GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, descriptors,
-                                               &engine);
-  GetActiveIMEState()->ChangeInputMethod(ime_id, false);
-  GetActiveIMEState()->EnableInputView();
+  manager_->GetActiveIMEState()->SetEnabledExtensionImes(&enabled_imes);
+  manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1,
+                                                         descriptors, &engine);
+  manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false);
+  manager_->GetActiveIMEState()->EnableInputView();
 
   const GURL overridden_url_emoji(
       "chrome-extension://"
@@ -1398,11 +1380,11 @@
       "us.compact.qwerty&name=keyboard_us");
 
   manager_->OverrideKeyboardKeyset(chromeos::input_method::ImeKeyset::kEmoji);
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(overridden_url_emoji.spec()));
 
-  GetActiveIMEState()->EnableInputView();
-  EXPECT_THAT(GetActiveIMEState()->GetInputViewUrl().spec(),
+  manager_->GetActiveIMEState()->EnableInputView();
+  EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(),
               ::testing::StartsWith(overridden_url_emoji.spec()));
 }
 
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc
index f2fa5a2e..046bf85 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc
@@ -184,10 +184,7 @@
         !file_manager::util::ConvertFileSystemURLToPathInsideVM(
             profile, url, vm_mount, /*map_crostini_home=*/false, &file_path)) {
       return std::move(callback).Run(
-          file_manager::util::GetMyFilesFolderForProfile(profile).IsParent(
-              url.path())
-              ? LaunchPluginVmAppResult::FAILED_DIRECTORY_NOT_SHARED
-              : LaunchPluginVmAppResult::FAILED_FILE_ON_EXTERNAL_DRIVE,
+          LaunchPluginVmAppResult::FAILED_DIRECTORY_NOT_SHARED,
           "Only files in shared dirs are supported. Got: " + url.DebugString());
     }
     // Convert slashes: '/' => '\'.
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h
index ebcca6f..f059297 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h
@@ -27,7 +27,6 @@
   SUCCESS,
   FAILED,
   FAILED_DIRECTORY_NOT_SHARED,
-  FAILED_FILE_ON_EXTERNAL_DRIVE,
 };
 
 using LaunchArg = absl::variant<storage::FileSystemURL, std::string>;
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc
index 5f5dc81..af5ec28 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc
@@ -202,7 +202,7 @@
   LaunchPluginVmApp(&profile_, app_id_, {url},
                     base::BindOnce(capture_result, &actual_result));
   task_environment_.RunUntilIdle();
-  EXPECT_EQ(LaunchPluginVmAppResult::FAILED_FILE_ON_EXTERNAL_DRIVE,
+  EXPECT_EQ(LaunchPluginVmAppResult::FAILED_DIRECTORY_NOT_SHARED,
             actual_result);
 }
 
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
index 0f7013a..230731f 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
@@ -108,7 +108,7 @@
 
   void RunDownloadActionCallback(google_apis::DriveApiErrorCode error,
                                  const base::FilePath& temp_file) {
-    download_action_callback_.Run(error, temp_file);
+    std::move(download_action_callback_).Run(error, temp_file);
   }
 
   void RunGetContentCallback(google_apis::DriveApiErrorCode error,
@@ -126,10 +126,10 @@
   google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& /*cache_path*/,
       const std::string& /*resource_id*/,
-      const DownloadActionCallback& download_action_callback,
+      DownloadActionCallback download_action_callback,
       const GetContentCallback& get_content_callback,
       ProgressCallback progress_callback) override {
-    download_action_callback_ = download_action_callback;
+    download_action_callback_ = std::move(download_action_callback);
     get_content_callback_ = get_content_callback;
     progress_callback_ = std::move(progress_callback);
 
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
index 15eef6cf..e269aa7 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -69,6 +69,8 @@
 #include "chromeos/dbus/cryptohome/tpm_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/disks/disk_mount_manager.h"
@@ -1484,8 +1486,10 @@
       base::BindOnce(&ReadFirmwareVersion),
       base::BindOnce(&DeviceStatusCollector::OnOSFirmware,
                      weak_factory_.GetWeakPtr()));
-  chromeos::tpm_util::GetTpmVersion(base::BindOnce(
-      &DeviceStatusCollector::OnTpmVersion, weak_factory_.GetWeakPtr()));
+  chromeos::TpmManagerClient::Get()->GetVersionInfo(
+      ::tpm_manager::GetVersionInfoRequest(),
+      base::BindOnce(&DeviceStatusCollector::OnGetTpmVersion,
+                     weak_factory_.GetWeakPtr()));
 
   pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
   pref_change_registrar_->Init(pref_service_);
@@ -2052,12 +2056,12 @@
 
   em::TpmVersionInfo* const tpm_version_info =
       status->mutable_tpm_version_info();
-  tpm_version_info->set_family(tpm_version_info_.family);
-  tpm_version_info->set_spec_level(tpm_version_info_.spec_level);
-  tpm_version_info->set_manufacturer(tpm_version_info_.manufacturer);
-  tpm_version_info->set_tpm_model(tpm_version_info_.tpm_model);
-  tpm_version_info->set_firmware_version(tpm_version_info_.firmware_version);
-  tpm_version_info->set_vendor_specific(tpm_version_info_.vendor_specific);
+  tpm_version_info->set_family(tpm_version_reply_.family());
+  tpm_version_info->set_spec_level(tpm_version_reply_.spec_level());
+  tpm_version_info->set_manufacturer(tpm_version_reply_.manufacturer());
+  tpm_version_info->set_tpm_model(tpm_version_reply_.tpm_model());
+  tpm_version_info->set_firmware_version(tpm_version_reply_.firmware_version());
+  tpm_version_info->set_vendor_specific(tpm_version_reply_.vendor_specific());
 
   return true;
 }
@@ -2708,9 +2712,12 @@
   firmware_fetch_error_ = version.second;
 }
 
-void DeviceStatusCollector::OnTpmVersion(
-    const chromeos::CryptohomeClient::TpmVersionInfo& tpm_version_info) {
-  tpm_version_info_ = tpm_version_info;
+void DeviceStatusCollector::OnGetTpmVersion(
+    const ::tpm_manager::GetVersionInfoReply& reply) {
+  if (reply.status() != ::tpm_manager::STATUS_SUCCESS) {
+    LOG(WARNING) << "Failed to get tpm version; status: " << reply.status();
+  }
+  tpm_version_reply_ = reply;
 }
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.h b/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
index 61cf9b9..aa054e9c 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
@@ -17,12 +17,12 @@
 #include "base/callback_list.h"
 #include "base/compiler_specific.h"
 #include "base/containers/circular_deque.h"
-#include "base/time/default_clock.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/policy/status_collector/app_info_generator.h"
@@ -30,6 +30,7 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_member.h"
@@ -256,8 +257,9 @@
   // Callbacks from chromeos::VersionLoader.
   void OnOSVersion(const std::string& version);
   void OnOSFirmware(std::pair<const std::string&, const std::string&> version);
-  void OnTpmVersion(
-      const chromeos::CryptohomeClient::TpmVersionInfo& tpm_version_info);
+
+  // Callbacks from `chromeos::TpmManagerClient`.
+  void OnGetTpmVersion(const ::tpm_manager::GetVersionInfoReply& reply);
 
   void GetDeviceStatus(scoped_refptr<DeviceStatusCollectorState> state);
   void GetSessionStatus(scoped_refptr<DeviceStatusCollectorState> state);
@@ -379,7 +381,7 @@
   std::string os_version_;
   std::string firmware_version_;
   std::string firmware_fetch_error_;
-  chromeos::CryptohomeClient::TpmVersionInfo tpm_version_info_;
+  ::tpm_manager::GetVersionInfoReply tpm_version_reply_;
 
   struct ResourceUsage {
     // Sample of percentage-of-CPU-used.
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index 99702ed..0a7ebd3f0 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -66,6 +66,7 @@
 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
@@ -798,11 +799,13 @@
     chromeos::CrasAudioHandler::InitializeForTesting();
     chromeos::CryptohomeClient::InitializeFake();
     chromeos::PowerManagerClient::InitializeFake();
+    chromeos::TpmManagerClient::InitializeFake();
     chromeos::LoginState::Initialize();
   }
 
   ~DeviceStatusCollectorTest() override {
     chromeos::LoginState::Shutdown();
+    chromeos::TpmManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
     chromeos::CryptohomeClient::Shutdown();
     chromeos::CrasAudioHandler::Shutdown();
@@ -1529,6 +1532,24 @@
   EXPECT_TRUE(device_status_.has_firmware_version());
   EXPECT_TRUE(device_status_.has_tpm_version_info());
 
+  // Expect tpm version info is still set (with an empty one) regardless of
+  // D-Bus error.
+  chromeos::TpmManagerClient::Get()
+      ->GetTestInterface()
+      ->mutable_version_info_reply()
+      ->set_status(::tpm_manager::STATUS_DBUS_ERROR);
+  GetStatus();
+  EXPECT_TRUE(device_status_.has_browser_version());
+  EXPECT_TRUE(device_status_.has_channel());
+  EXPECT_TRUE(device_status_.has_os_version());
+  EXPECT_TRUE(device_status_.has_firmware_version());
+  EXPECT_TRUE(device_status_.has_tpm_version_info());
+  // Reset the version info reply just in case the rest of tests get affected.
+  chromeos::TpmManagerClient::Get()
+      ->GetTestInterface()
+      ->mutable_version_info_reply()
+      ->clear_status();
+
   // When the pref to collect this data is not enabled, expect that none of
   // the fields are present in the protobuf.
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
diff --git a/chrome/browser/chromeos/policy/status_uploader_unittest.cc b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
index 9e844f5..548ebe32 100644
--- a/chrome/browser/chromeos/policy/status_uploader_unittest.cc
+++ b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
@@ -17,8 +17,10 @@
 #include "chrome/browser/chromeos/policy/status_collector/device_status_collector.h"
 #include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
@@ -85,6 +87,7 @@
 
     chromeos::CryptohomeClient::InitializeFake();
     chromeos::PowerManagerClient::InitializeFake();
+    chromeos::TpmManagerClient::InitializeFake();
     client_.SetDMToken("dm_token");
     collector_.reset(new MockDeviceStatusCollector(&prefs_));
 
@@ -95,6 +98,7 @@
 
   void TearDown() override {
     content::RunAllTasksUntilIdle();
+    chromeos::TpmManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
     chromeos::CryptohomeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
diff --git a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
index e271da1b..a048a96 100644
--- a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
+++ b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
@@ -36,18 +36,19 @@
                                        PageCallback page_callback,
                                        CompletionCallback completion_callback) {
   if (scan_data_.has_value()) {
-    constexpr uint32_t page_number = 1;
-    if (progress_callback) {
-      for (const uint32_t progress : {7, 22, 40, 42, 59, 74, 95}) {
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE,
-            base::BindOnce(progress_callback, progress, page_number));
+    uint32_t page_number = 1;
+    for (const std::string& page_data : scan_data_.value()) {
+      if (progress_callback) {
+        for (const uint32_t progress : {7, 22, 40, 42, 59, 74, 95}) {
+          base::ThreadTaskRunnerHandle::Get()->PostTask(
+              FROM_HERE,
+              base::BindOnce(progress_callback, progress, page_number));
+        }
       }
-    }
 
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(page_callback, scan_data_.value(), page_number));
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(page_callback, page_data, page_number++));
+    }
   }
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -72,7 +73,7 @@
 }
 
 void FakeLorgnetteScannerManager::SetScanResponse(
-    const base::Optional<std::string>& scan_data) {
+    const base::Optional<std::vector<std::string>>& scan_data) {
   scan_data_ = scan_data;
 }
 
diff --git a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h
index ad77c1c..b277875 100644
--- a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h
+++ b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h
@@ -45,12 +45,13 @@
           scanner_capabilities);
 
   // Sets the response returned by Scan().
-  void SetScanResponse(const base::Optional<std::string>& scan_data);
+  void SetScanResponse(
+      const base::Optional<std::vector<std::string>>& scan_data);
 
  private:
   std::vector<std::string> scanner_names_;
   base::Optional<lorgnette::ScannerCapabilities> scanner_capabilities_;
-  base::Optional<std::string> scan_data_;
+  base::Optional<std::vector<std::string>> scan_data_;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/scanning/scan_service.cc b/chrome/browser/chromeos/scanning/scan_service.cc
index dca4c84..789811c96 100644
--- a/chrome/browser/chromeos/scanning/scan_service.cc
+++ b/chrome/browser/chromeos/scanning/scan_service.cc
@@ -52,14 +52,13 @@
   return std::string(jpg_img.begin(), jpg_img.end());
 }
 
-// Saves |scanned_image| to a file after converting it if necessary. Returns
-// true if the save succeeds.
-bool SavePage(const base::FilePath& scan_to_path,
-              const mojo_ipc::FileType file_type,
-              std::string scanned_image,
-              uint32_t page_number,
-              const base::Time::Exploded& start_time) {
-  std::string filename;
+// Saves |scanned_image| to a file after converting it if necessary. Returns the
+// file path to the saved file if the save succeeds.
+base::FilePath SavePage(const base::FilePath& scan_to_path,
+                        const mojo_ipc::FileType file_type,
+                        std::string scanned_image,
+                        uint32_t page_number,
+                        const base::Time::Exploded& start_time) {
   std::string file_ext;
   switch (file_type) {
     case mojo_ipc::FileType::kPng:
@@ -69,25 +68,25 @@
       file_ext = "jpg";
       scanned_image = PngToJpg(scanned_image);
       if (scanned_image.empty())
-        return false;
+        return base::FilePath();
 
       break;
     default:
       LOG(ERROR) << "Selected file type not supported.";
-      return false;
+      return base::FilePath();
   }
 
-  filename = base::StringPrintf(
+  const std::string filename = base::StringPrintf(
       "scan_%02d%02d%02d-%02d%02d%02d_%d.%s", start_time.year, start_time.month,
       start_time.day_of_month, start_time.hour, start_time.minute,
       start_time.second, page_number, file_ext.c_str());
   const auto file_path = scan_to_path.Append(filename);
   if (!base::WriteFile(file_path, scanned_image)) {
     LOG(ERROR) << "Failed to save scanned image: " << file_path.value().c_str();
-    return false;
+    return base::FilePath();
   }
 
-  return true;
+  return file_path;
 }
 
 }  // namespace
@@ -147,6 +146,7 @@
 
   base::Time::Now().LocalExplode(&start_time_);
   save_failed_ = false;
+  last_scanned_file_path_.clear();
   lorgnette_scanner_manager_->Scan(
       scanner_name, mojo::ConvertTo<lorgnette::ScanSettings>(settings),
       base::BindRepeating(&ScanService::OnProgressPercentReceived,
@@ -254,13 +254,17 @@
   scan_job_observer_->OnCancelComplete(success);
 }
 
-void ScanService::OnPageSaved(bool success) {
-  if (!success)
-    save_failed_ = true;
+void ScanService::OnPageSaved(const base::FilePath& saved_file_path) {
+  save_failed_ = save_failed_ || saved_file_path.empty();
+  last_scanned_file_path_ = save_failed_ ? base::FilePath() : saved_file_path;
 }
 
 void ScanService::OnAllPagesSaved(bool success) {
-  scan_job_observer_->OnScanComplete(success && !save_failed_);
+  save_failed_ = !success || save_failed_;
+  if (save_failed_)
+    last_scanned_file_path_.clear();
+
+  scan_job_observer_->OnScanComplete(!save_failed_, last_scanned_file_path_);
 }
 
 bool ScanService::FilePathSupported(const base::FilePath& file_path) {
diff --git a/chrome/browser/chromeos/scanning/scan_service.h b/chrome/browser/chromeos/scanning/scan_service.h
index f9087ce..91d7e85 100644
--- a/chrome/browser/chromeos/scanning/scan_service.h
+++ b/chrome/browser/chromeos/scanning/scan_service.h
@@ -101,7 +101,7 @@
   void OnCancelCompleted(bool success);
 
   // Called once the task runner finishes saving a page of a scan.
-  void OnPageSaved(bool success);
+  void OnPageSaved(const base::FilePath& saved_file_path);
 
   // Called once the task runner finishes saving the last page of a scan.
   void OnAllPagesSaved(bool success);
@@ -142,6 +142,9 @@
   // The time a scan was started. Used in filenames when saving scanned images.
   base::Time::Exploded start_time_;
 
+  // The file path of the last page scanned in a scan job.
+  base::FilePath last_scanned_file_path_;
+
   // Task runner used to convert and save scanned images.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
diff --git a/chrome/browser/chromeos/scanning/scan_service_unittest.cc b/chrome/browser/chromeos/scanning/scan_service_unittest.cc
index 8691f68..74fc2071 100644
--- a/chrome/browser/chromeos/scanning/scan_service_unittest.cc
+++ b/chrome/browser/chromeos/scanning/scan_service_unittest.cc
@@ -66,6 +66,23 @@
   return caps;
 }
 
+// Returns a vector of FilePaths to mimic saved scans.
+std::vector<base::FilePath> CreateSavedScanPaths(
+    const base::FilePath& dir,
+    const base::Time::Exploded& scan_time,
+    const std::string& type,
+    int num_pages_to_scan) {
+  std::vector<base::FilePath> file_paths;
+  file_paths.reserve(num_pages_to_scan);
+  for (int i = 1; i <= num_pages_to_scan; i++) {
+    file_paths.push_back(dir.Append(base::StringPrintf(
+        "scan_%02d%02d%02d-%02d%02d%02d_%d.%s", scan_time.year, scan_time.month,
+        scan_time.day_of_month, scan_time.hour, scan_time.minute,
+        scan_time.second, i, type.c_str())));
+  }
+  return file_paths;
+}
+
 }  // namespace
 
 class FakeScanJobObserver : public mojo_ipc::ScanJobObserver {
@@ -86,7 +103,11 @@
     page_complete_ = true;
   }
 
-  void OnScanComplete(bool success) override { scan_success_ = success; }
+  void OnScanComplete(bool success,
+                      const base::FilePath& last_scanned_file_path) override {
+    scan_success_ = success;
+    last_scanned_file_path_ = last_scanned_file_path;
+  }
 
   void OnCancelComplete(bool success) override {
     cancel_scan_success_ = success;
@@ -111,11 +132,17 @@
   // Returns true if the cancel scan request completed successfully.
   bool cancel_scan_success() const { return cancel_scan_success_; }
 
+  // Returns the file path of the file saved last.
+  base::FilePath last_scanned_file_path() const {
+    return last_scanned_file_path_;
+  }
+
  private:
   uint32_t progress_ = 0;
   bool page_complete_ = false;
   bool scan_success_ = false;
   bool cancel_scan_success_ = false;
+  base::FilePath last_scanned_file_path_;
   mojo::Receiver<mojo_ipc::ScanJobObserver> receiver_{this};
 };
 
@@ -265,7 +292,8 @@
 TEST_F(ScanServiceTest, ScanWithUnsupportedFilePath) {
   fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
       {kFirstTestScannerName});
-  fake_lorgnette_scanner_manager_.SetScanResponse("TestData");
+  const std::vector<std::string> scan_data = {"TestData"};
+  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
   auto scanners = GetScanners();
   ASSERT_EQ(scanners.size(), 1u);
 
@@ -281,7 +309,9 @@
 TEST_F(ScanServiceTest, Scan) {
   fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
       {kFirstTestScannerName});
-  fake_lorgnette_scanner_manager_.SetScanResponse("TestData");
+  const std::vector<std::string> scan_data = {"TestData1", "TestData2",
+                                              "TestData3"};
+  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
   auto scanners = GetScanners();
   ASSERT_EQ(scanners.size(), 1u);
 
@@ -294,18 +324,20 @@
   settings.scan_to_path = temp_dir_.GetPath();
   std::map<std::string, mojo_ipc::FileType> file_types = {
       {"png", mojo_ipc::FileType::kPng}, {"jpg", mojo_ipc::FileType::kJpg}};
-  base::FilePath saved_scan_path;
   for (const auto& type : file_types) {
-    saved_scan_path = temp_dir_.GetPath().Append(base::StringPrintf(
-        "scan_%02d%02d%02d-%02d%02d%02d_1.%s", scan_time.year, scan_time.month,
-        scan_time.day_of_month, scan_time.hour, scan_time.minute,
-        scan_time.second, type.first.c_str()));
-    EXPECT_FALSE(base::PathExists(saved_scan_path));
+    const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
+        temp_dir_.GetPath(), scan_time, type.first, scan_data.size());
+    for (const auto& saved_scan_path : saved_scan_paths)
+      EXPECT_FALSE(base::PathExists(saved_scan_path));
 
     settings.file_type = type.second;
     EXPECT_TRUE(Scan(scanners[0]->id, settings.Clone()));
-    EXPECT_TRUE(base::PathExists(saved_scan_path));
+    for (const auto& saved_scan_path : saved_scan_paths)
+      EXPECT_TRUE(base::PathExists(saved_scan_path));
+
     EXPECT_TRUE(fake_scan_job_observer_.scan_success());
+    EXPECT_EQ(saved_scan_paths.back(),
+              fake_scan_job_observer_.last_scanned_file_path());
   }
 }
 
@@ -313,7 +345,8 @@
 TEST_F(ScanServiceTest, CancelScanBeforeScanCompletes) {
   fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
       {kFirstTestScannerName});
-  fake_lorgnette_scanner_manager_.SetScanResponse("TestData");
+  const std::vector<std::string> scan_data = {"TestData"};
+  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
   auto scanners = GetScanners();
   ASSERT_EQ(scanners.size(), 1u);
 
diff --git a/chrome/browser/chromeos/settings/device_settings_test_helper.cc b/chrome/browser/chromeos/settings/device_settings_test_helper.cc
index a973e85..3dec084 100644
--- a/chrome/browser/chromeos/settings/device_settings_test_helper.cc
+++ b/chrome/browser/chromeos/settings/device_settings_test_helper.cc
@@ -12,8 +12,10 @@
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "content/public/browser/browser_thread.h"
@@ -56,6 +58,7 @@
   dbus_setter_ = DBusThreadManager::GetSetterForTesting();
   CryptohomeClient::InitializeFake();
   PowerManagerClient::InitializeFake();
+  TpmManagerClient::InitializeFake();
   OwnerSettingsServiceChromeOSFactory::SetDeviceSettingsServiceForTesting(
       device_settings_service_.get());
   OwnerSettingsServiceChromeOSFactory::GetInstance()->SetOwnerKeyUtilForTesting(
@@ -79,6 +82,7 @@
   FlushDeviceSettings();
   device_settings_service_->UnsetSessionManager();
   device_settings_service_.reset();
+  TpmManagerClient::Shutdown();
   PowerManagerClient::Shutdown();
   CryptohomeClient::Shutdown();
   DBusThreadManager::Shutdown();
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc
index 9201605..984d404f 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -1049,9 +1049,20 @@
 }
 
 void SmbService::SuspendDone(const base::TimeDelta& sleep_duration) {
-  for (auto it = smbfs_shares_.begin(); it != smbfs_shares_.end(); ++it) {
-    SmbFsShare* share = it->second.get();
-    const std::string mount_id = share->mount_id();
+  // Don't iterate directly over the share map during the remount
+  // process as shares can be removed on failure in OnSmbfsMountDone.
+  std::vector<std::string> mount_ids;
+  for (const auto& s : smbfs_shares_)
+    mount_ids.push_back(s.first);
+
+  for (const auto& mount_id : mount_ids) {
+    auto share_it = smbfs_shares_.find(mount_id);
+    if (share_it == smbfs_shares_.end()) {
+      LOG(WARNING) << "Smbfs mount id " << mount_id
+                   << " no longer present during remount after suspend";
+      continue;
+    }
+    SmbFsShare* share = share_it->second.get();
 
     // Don't try to reconnect as we race the network stack in getting an IP
     // address.
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 81b40c50..7422d51 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -2723,8 +2723,9 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH) && \
     (!defined(NDEBUG) || defined(MEMORY_SANITIZER))
 #define MAYBE_SaveLargeImage DISABLED_SaveLargeImage
-#elif defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX)
-// Flaking on Windows, macOS, and Linux. https://crbug.com/1141263
+#elif defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \
+    defined(OS_CHROMEOS)
+// Flaking on Windows, macOS, Linux, ChromeOS. https://crbug.com/1141263
 #define MAYBE_SaveLargeImage DISABLED_SaveLargeImage
 #else
 #define MAYBE_SaveLargeImage SaveLargeImage
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index fc5717d..f2f37f23c 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -1280,6 +1280,8 @@
   sources = [
     "external_testing_loader.cc",
     "external_testing_loader.h",
+    "menu_manager_test_observer.cc",
+    "menu_manager_test_observer.h",
   ]
 
   deps = [
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index c43bada..2dfb43e 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -766,8 +766,8 @@
 using DeclarativeNetRequestBrowserTest_Unpacked =
     DeclarativeNetRequestBrowserTest;
 
-#if (defined(OS_WIN) || defined(OS_MAC)) && !defined(NDEBUG)
-// TODO: test times out on win7-debug. http://crbug.com/900447.
+#if defined(OS_WIN) || (defined(OS_MAC) && !defined(NDEBUG))
+// TODO: test times out on win. http://crbug.com/900447.
 // Also times out on mac-debug: https://crbug.com/900447
 #define MAYBE_BlockRequests_UrlFilter DISABLED_BlockRequests_UrlFilter
 #else
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index a00ccbb..fe5df02 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -3030,7 +3030,14 @@
 
 // Regression test for http://crbug.com/996940. Requests that redirected to an
 // appcache handled URL could have request ID collisions.
-IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, RedirectToAppCacheRequest) {
+// This test is flaky on Linux: https://crbug.com/1094834.
+#if defined(OS_LINUX)
+#define MAYBE_RedirectToAppCacheRequest DISABLED_RedirectToAppCacheRequest
+#else
+#define MAYBE_RedirectToAppCacheRequest RedirectToAppCacheRequest
+#endif
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+                       MAYBE_RedirectToAppCacheRequest) {
   // Use the embedded test server to support server-redirect, but serve
   // appcache from a fixed port using the url loader interceptor below
   // so that the appcache origin trial works.
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
index 18045b8..bec6b14 100644
--- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
+++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -24,6 +24,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "ash/keyboard/ui/resources/keyboard_resource_util.h"
+#include "base/command_line.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_string_util.h"
 #include "third_party/ink/grit/ink_resources.h"
@@ -195,6 +196,16 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   LazyInitData();
+
+#if defined(OS_CHROMEOS)
+  if (extension_id == extension_misc::kFilesManagerAppId) {
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    // Disable $i18n{} template JS string replacement during JS code coverage.
+    if (command_line->HasSwitch("devtools-code-coverage"))
+      return nullptr;
+  }
+#endif
+
   auto it = data_->template_replacements().find(extension_id);
   return it != data_->template_replacements().end() ? &it->second : nullptr;
 }
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc
index e863cc1..189def8 100644
--- a/chrome/browser/extensions/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/extensions/browsertest_util.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/lazy_background_page_test_util.h"
+#include "chrome/browser/extensions/menu_manager_test_observer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
@@ -94,54 +95,6 @@
   ScopedObserver<StateStore, StateStore::TestObserver> observed_{this};
 };
 
-// Observe when a extension's context menu data is read from storage.
-class MenuManagerObserver : public MenuManager::TestObserver {
- public:
-  explicit MenuManagerObserver(MenuManager* menu_manager)
-      : menu_manager_(menu_manager) {
-    observed_.Add(menu_manager_);
-  }
-
-  ~MenuManagerObserver() final = default;
-
-  void WaitForExtension(const std::string& extension_id) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    // The extension's menus may have already been loaded before we were
-    // able to observe it.
-    if (MenusItemsFound(extension_id))
-      return;
-
-    if (ids_with_reads_.count(extension_id) == 0) {
-      waiting_for_id_ = extension_id;
-      run_loop_.Run();
-      DCHECK(MenusItemsFound(extension_id));
-    }
-  }
-
-  void DidReadFromStorage(const std::string& extension_id) override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    if (extension_id == waiting_for_id_) {
-      run_loop_.Quit();
-    } else {
-      ids_with_reads_.insert(extension_id);
-    }
-  }
-
- private:
-  bool MenusItemsFound(const std::string& extension_id) {
-    const extensions::MenuItem::ExtensionKey key(extension_id);
-    return menu_manager_->MenuItems(key) &&
-           !menu_manager_->MenuItems(key)->empty();
-  }
-
-  MenuManager* const menu_manager_;
-  std::set<std::string> ids_with_reads_;
-  std::string waiting_for_id_;
-  base::RunLoop run_loop_;
-  ScopedObserver<MenuManager, MenuManager::TestObserver> observed_{this};
-};
-
 constexpr char kPersistentExtensionId[] = "cmgkkmeeoiceijkpmaabbmpgnkpaaela";
 
 }  // namespace
@@ -458,7 +411,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ExtensionContextMenuLazyTest, Persistent) {
-  MenuManagerObserver observer(menu_manager());
+  extensions::MenuManagerTestObserver observer(menu_manager());
   ResultCatcher catcher;
 
   // Wait for the context menu to finish loading.
diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc
index b1619d61..78183248 100644
--- a/chrome/browser/extensions/menu_manager.cc
+++ b/chrome/browser/extensions/menu_manager.cc
@@ -821,6 +821,9 @@
     }
   }
 
+  for (TestObserver& observer : observers_)
+    observer.WillWriteToStorage(extension->id());
+
   if (store_) {
     store_->SetExtensionValue(extension->id(), kContextMenusKey,
                               MenuItemsToValue(all_items));
diff --git a/chrome/browser/extensions/menu_manager.h b/chrome/browser/extensions/menu_manager.h
index bdb0c06d..c8bf74c 100644
--- a/chrome/browser/extensions/menu_manager.h
+++ b/chrome/browser/extensions/menu_manager.h
@@ -296,7 +296,8 @@
   class TestObserver : public base::CheckedObserver {
    public:
     ~TestObserver() override = default;
-    virtual void DidReadFromStorage(const std::string& extension_id) = 0;
+    virtual void DidReadFromStorage(const std::string& extension_id) {}
+    virtual void WillWriteToStorage(const std::string& extension_id) {}
   };
 
   MenuManager(content::BrowserContext* context, StateStore* store_);
diff --git a/chrome/browser/extensions/menu_manager_test_observer.cc b/chrome/browser/extensions/menu_manager_test_observer.cc
new file mode 100644
index 0000000..57c6c01
--- /dev/null
+++ b/chrome/browser/extensions/menu_manager_test_observer.cc
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/menu_manager_test_observer.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace extensions {
+
+MenuManagerTestObserver::MenuManagerTestObserver(MenuManager* menu_manager)
+    : menu_manager_(menu_manager) {
+  observation_.Observe(menu_manager_);
+}
+
+MenuManagerTestObserver::~MenuManagerTestObserver() = default;
+
+void MenuManagerTestObserver::WaitForExtension(
+    const ExtensionId& extension_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // The extension's menus may have already been loaded before we were
+  // able to observe it.
+  if (MenusItemsFound(extension_id))
+    return;
+
+  if (ids_with_reads_.count(extension_id) == 0) {
+    waiting_for_id_ = extension_id;
+    run_loop_.Run();
+    DCHECK(MenusItemsFound(extension_id));
+  }
+}
+
+void MenuManagerTestObserver::DidReadFromStorage(
+    const ExtensionId& extension_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  ids_with_reads_.insert(extension_id);
+  if (extension_id == waiting_for_id_) {
+    run_loop_.Quit();
+  }
+}
+
+void MenuManagerTestObserver::WillWriteToStorage(
+    const ExtensionId& extension_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  ids_with_writes_.insert(extension_id);
+  if (extension_id == waiting_for_id_) {
+    run_loop_.Quit();
+  }
+}
+
+bool MenuManagerTestObserver::MenusItemsFound(const ExtensionId& extension_id) {
+  const MenuItem::ExtensionKey key(extension_id);
+  return menu_manager_->MenuItems(key) &&
+         !menu_manager_->MenuItems(key)->empty();
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/menu_manager_test_observer.h b/chrome/browser/extensions/menu_manager_test_observer.h
new file mode 100644
index 0000000..4023055
--- /dev/null
+++ b/chrome/browser/extensions/menu_manager_test_observer.h
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_MENU_MANAGER_TEST_OBSERVER_H_
+#define CHROME_BROWSER_EXTENSIONS_MENU_MANAGER_TEST_OBSERVER_H_
+
+#include "chrome/browser/extensions/menu_manager.h"
+
+#include <set>
+#include <string>
+
+#include "base/run_loop.h"
+#include "base/scoped_observation.h"
+#include "extensions/common/extension_id.h"
+
+namespace extensions {
+
+class MenuManagerTestObserver : public MenuManager::TestObserver {
+ public:
+  explicit MenuManagerTestObserver(MenuManager* menu_manager);
+
+  ~MenuManagerTestObserver() override;
+
+  MenuManagerTestObserver(const MenuManagerTestObserver&) = delete;
+  MenuManagerTestObserver& operator=(const MenuManagerTestObserver&) = delete;
+
+  // MenuManager::TestObserver overrides.
+  void DidReadFromStorage(const ExtensionId& extension_id) override;
+  void WillWriteToStorage(const ExtensionId& extension_id) override;
+
+  // Wait for a MenuManager storage read or write for the specified
+  // extension.
+  void WaitForExtension(const ExtensionId& extension_id);
+
+  bool did_read_for_extension(const ExtensionId& extension_id) const {
+    return ids_with_reads_.count(extension_id) != 0;
+  }
+
+  bool will_write_for_extension(const ExtensionId& extension_id) const {
+    return ids_with_writes_.count(extension_id) != 0;
+  }
+
+ private:
+  bool MenusItemsFound(const ExtensionId& extension_id);
+
+  MenuManager* const menu_manager_;
+  std::set<ExtensionId> ids_with_reads_;
+  std::set<ExtensionId> ids_with_writes_;
+  ExtensionId waiting_for_id_;
+  base::RunLoop run_loop_;
+  base::ScopedObservation<MenuManager, MenuManager::TestObserver> observation_{
+      this};
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_MENU_MANAGER_TEST_OBSERVER_H_
diff --git a/chrome/browser/extensions/menu_manager_unittest.cc b/chrome/browser/extensions/menu_manager_unittest.cc
index 3d47a2bd..6b345762 100644
--- a/chrome/browser/extensions/menu_manager_unittest.cc
+++ b/chrome/browser/extensions/menu_manager_unittest.cc
@@ -18,6 +18,8 @@
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
+#include "chrome/browser/extensions/menu_manager.h"
+#include "chrome/browser/extensions/menu_manager_test_observer.h"
 #include "chrome/browser/extensions/test_extension_prefs.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/common/chrome_paths.h"
@@ -32,7 +34,9 @@
 #include "extensions/browser/event_router_factory.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/state_store.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/manifest_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -63,7 +67,7 @@
   }
 
   // Returns a test item.
-  std::unique_ptr<MenuItem> CreateTestItem(Extension* extension,
+  std::unique_ptr<MenuItem> CreateTestItem(const Extension* extension,
                                            bool incognito = false) {
     MenuItem::Type type = MenuItem::NORMAL;
     MenuItem::ContextList contexts(MenuItem::ALL);
@@ -75,7 +79,7 @@
   }
 
   // Returns a test item with the given string ID.
-  std::unique_ptr<MenuItem> CreateTestItemWithID(Extension* extension,
+  std::unique_ptr<MenuItem> CreateTestItemWithID(const Extension* extension,
                                                  const std::string& string_id) {
     MenuItem::Type type = MenuItem::NORMAL;
     MenuItem::ContextList contexts(MenuItem::ALL);
@@ -88,7 +92,7 @@
 
   // Creates and returns a test Extension. The caller does *not* own the return
   // value.
-  Extension* AddExtension(const std::string& name) {
+  const Extension* AddExtension(const std::string& name) {
     scoped_refptr<Extension> extension = prefs_.AddExtension(name);
     extensions_.push_back(extension);
     return extension.get();
@@ -109,7 +113,7 @@
 
 // Tests adding, getting, and removing items.
 TEST_F(MenuManagerTest, AddGetRemoveItems) {
-  Extension* extension = AddExtension("test");
+  const Extension* extension = AddExtension("test");
 
   // Add a new item, make sure you can get it back.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension);
@@ -155,7 +159,7 @@
   ASSERT_FALSE(manager_.AddContextItem(extension, std::move(item2too)));
 
   // But the same string ID should not collide with another extension.
-  Extension* extension2 = AddExtension("test2");
+  const Extension* extension2 = AddExtension("test2");
   std::unique_ptr<MenuItem> item2other =
       CreateTestItemWithID(extension2, "id2");
   ASSERT_TRUE(manager_.AddContextItem(extension2, std::move(item2other)));
@@ -163,9 +167,9 @@
 
 // Test adding/removing child items.
 TEST_F(MenuManagerTest, ChildFunctions) {
-  Extension* extension1 = AddExtension("1111");
-  Extension* extension2 = AddExtension("2222");
-  Extension* extension3 = AddExtension("3333");
+  const Extension* extension1 = AddExtension("1111");
+  const Extension* extension2 = AddExtension("2222");
+  const Extension* extension3 = AddExtension("3333");
 
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1);
   MenuItem* item1_ptr = item1.get();
@@ -221,7 +225,7 @@
 }
 
 TEST_F(MenuManagerTest, PopulateFromValue) {
-  Extension* extension = AddExtension("test");
+  const Extension* extension = AddExtension("test");
 
   bool incognito = true;
   int type = MenuItem::CHECKBOX;
@@ -282,7 +286,7 @@
 
 // Tests that deleting a parent properly removes descendants.
 TEST_F(MenuManagerTest, DeleteParent) {
-  Extension* extension = AddExtension("1111");
+  const Extension* extension = AddExtension("1111");
 
   // Set up 5 items to add.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension);
@@ -354,7 +358,7 @@
 
 // Tests changing parents.
 TEST_F(MenuManagerTest, ChangeParent) {
-  Extension* extension1 = AddExtension("1111");
+  const Extension* extension1 = AddExtension("1111");
 
   // First create two items and add them both to the manager.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1);
@@ -424,7 +428,7 @@
   ASSERT_EQ(item3_ptr, item1_ptr->children()[0].get());
 
   // Make sure you can't move a node to be a child of another extension's item.
-  Extension* extension2 = AddExtension("2222");
+  const Extension* extension2 = AddExtension("2222");
   std::unique_ptr<MenuItem> item4 = CreateTestItem(extension2);
   MenuItem* item4_ptr = item4.get();
   ASSERT_TRUE(manager_.AddContextItem(extension2, std::move(item4)));
@@ -443,7 +447,7 @@
   ASSERT_TRUE(notifier != NULL);
 
   // Create a test extension.
-  Extension* extension1 = AddExtension("1111");
+  const Extension* extension1 = AddExtension("1111");
 
   // Create an MenuItem and put it into the manager.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1);
@@ -455,7 +459,7 @@
       1u, manager_.MenuItems(MenuItem::ExtensionKey(extension1->id()))->size());
 
   // Create a menu item with a different extension id and add it to the manager.
-  Extension* extension2 = AddExtension("2222");
+  const Extension* extension2 = AddExtension("2222");
   std::unique_ptr<MenuItem> item2 = CreateTestItem(extension2);
   MenuItem* item2_ptr = item2.get();
   ASSERT_NE(item1_ptr->extension_id(), item2->extension_id());
@@ -516,7 +520,7 @@
   manager_.RemoveAllContextItems(MenuItem::ExtensionKey("CCCC"));
 
   // Add 2 top-level and one child item for extension 1.
-  Extension* extension1 = AddExtension("1111");
+  const Extension* extension1 = AddExtension("1111");
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1);
   std::unique_ptr<MenuItem> item2 = CreateTestItem(extension1);
   std::unique_ptr<MenuItem> item3 = CreateTestItem(extension1);
@@ -526,7 +530,7 @@
   ASSERT_TRUE(manager_.AddChildItem(item1_ptr->id(), std::move(item3)));
 
   // Add one top-level item for extension 2.
-  Extension* extension2 = AddExtension("2222");
+  const Extension* extension2 = AddExtension("2222");
   std::unique_ptr<MenuItem> item4 = CreateTestItem(extension2);
   ASSERT_TRUE(manager_.AddContextItem(extension2, std::move(item4)));
 
@@ -548,7 +552,7 @@
 // Tests that removing all items one-by-one doesn't leave an entry around.
 TEST_F(MenuManagerTest, RemoveOneByOne) {
   // Add 2 test items.
-  Extension* extension1 = AddExtension("1111");
+  const Extension* extension1 = AddExtension("1111");
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1);
   std::unique_ptr<MenuItem> item2 = CreateTestItem(extension1);
   std::unique_ptr<MenuItem> item3 = CreateTestItemWithID(extension1, "id3");
@@ -581,7 +585,7 @@
   params.selection_text = base::ASCIIToUTF16("Hello World");
   params.is_editable = false;
 
-  Extension* extension = AddExtension("test");
+  const Extension* extension = AddExtension("test");
   std::unique_ptr<MenuItem> parent = CreateTestItem(extension);
   std::unique_ptr<MenuItem> item = CreateTestItem(extension);
   MenuItem* item_ptr = item.get();
@@ -644,7 +648,7 @@
 
 // Test that there is always only one radio item selected.
 TEST_F(MenuManagerTest, SanitizeRadioButtons) {
-  Extension* extension = AddExtension("test");
+  const Extension* extension = AddExtension("test");
 
   // A single unchecked item should get checked.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension);
@@ -754,7 +758,7 @@
 // sanitized. More specifically, on initialization of the context menu, the
 // first item of each list should be checked.
 TEST_F(MenuManagerTest, SanitizeContextMenuWithMultipleRadioLists) {
-  Extension* extension = AddExtension("test");
+  const Extension* extension = AddExtension("test");
 
   // Create a radio list with two radio buttons.
   // Create first radio button.
@@ -796,7 +800,7 @@
 
 // Tests the RemoveAllIncognitoContextItems functionality.
 TEST_F(MenuManagerTest, RemoveAllIncognito) {
-  Extension* extension1 = AddExtension("1111");
+  const Extension* extension1 = AddExtension("1111");
   // Add 2 top-level and one child item for extension 1
   // with incognito 'true'.
   std::unique_ptr<MenuItem> item1 = CreateTestItem(extension1, true);
@@ -818,7 +822,7 @@
   ASSERT_TRUE(manager_.AddChildItem(item4_id, std::move(item6)));
 
   // Add one top-level item for extension 2.
-  Extension* extension2 = AddExtension("2222");
+  const Extension* extension2 = AddExtension("2222");
   std::unique_ptr<MenuItem> item7 = CreateTestItem(extension2);
   ASSERT_TRUE(manager_.AddContextItem(extension2, std::move(item7)));
 
@@ -833,4 +837,138 @@
   EXPECT_EQ(1u, manager_.MenuItems(key2)->size());
 }
 
+// TODO(https://crbug.com/1150988): This should be unified with the existing
+// version of this enum in ExtensionBrowserTest.
+enum class ContextType {
+  // A non-persistent background page/JS based extension.
+  kEventPage,
+  // A Service Worker based extension.
+  kServiceWorker,
+  // An extension with a persistent background page.
+  kPersistentBackground,
+};
+
+class MenuManagerStorageTest : public MenuManagerTest,
+                               public testing::WithParamInterface<ContextType> {
+ protected:
+  scoped_refptr<const Extension> AddEventPageExtension(
+      const std::string& name) {
+    base::DictionaryValue dictionary;
+    TestExtensionPrefs::AddDefaultManifestKeys(name, &dictionary);
+    base::Value value(base::Value::Type::LIST);
+    value.Append("background.js");
+    dictionary.SetPath(manifest_keys::kBackgroundScripts, std::move(value));
+    dictionary.SetPath(manifest_keys::kBackgroundPersistent,
+                       base::Value(false));
+    return prefs_.AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
+  }
+
+  scoped_refptr<const Extension> AddServiceWorkerExtension(
+      const std::string& name) {
+    base::DictionaryValue dictionary;
+    TestExtensionPrefs::AddDefaultManifestKeys(name, &dictionary);
+    dictionary.SetStringPath(manifest_keys::kBackgroundServiceWorkerScript,
+                             "background.js");
+    return prefs_.AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
+  }
+
+  scoped_refptr<const Extension> CreateTestExtension() {
+    static constexpr char kName[] = "1111";
+    switch (GetParam()) {
+      case ContextType::kPersistentBackground:
+        return AddExtension(kName);
+
+      case ContextType::kEventPage:
+        return AddEventPageExtension(kName);
+
+      case ContextType::kServiceWorker:
+        return AddServiceWorkerExtension(kName);
+    }
+  }
+
+  bool IsPersistent() const {
+    return GetParam() == ContextType::kPersistentBackground;
+  }
+
+  void FlushStateStore() {
+    StateStore* state_store =
+        ExtensionSystem::Get(profile_.get())->state_store();
+    base::RunLoop run_loop;
+    state_store->FlushForTesting(run_loop.QuitWhenIdleClosure());
+    run_loop.Run();
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(PersistentBackground,
+                         MenuManagerStorageTest,
+                         ::testing::Values(ContextType::kPersistentBackground));
+
+INSTANTIATE_TEST_SUITE_P(EventPage,
+                         MenuManagerStorageTest,
+                         ::testing::Values(ContextType::kEventPage));
+
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+                         MenuManagerStorageTest,
+                         ::testing::Values(ContextType::kServiceWorker));
+
+// Tests writing menus to and reading them from storage. Menus for
+// persistent background page-based extensions are not written to or
+// read from storage.
+TEST_P(MenuManagerStorageTest, WriteToAndReadFromStorage) {
+  // Observer reads and writes from storage for the MenuManager.
+  MenuManagerTestObserver observer(&manager_);
+
+  scoped_refptr<const Extension> extension = CreateTestExtension();
+  ASSERT_TRUE(extension);
+  ExtensionRegistry::Get(profile_.get())->AddEnabled(extension);
+  const MenuItem::ExtensionKey extension_key(extension->id());
+
+  // Add 2 top-level and one child item for the extension.
+  std::unique_ptr<MenuItem> item1 =
+      CreateTestItemWithID(extension.get(), "id1");
+  std::unique_ptr<MenuItem> item2 =
+      CreateTestItemWithID(extension.get(), "id2");
+  std::unique_ptr<MenuItem> item3 =
+      CreateTestItemWithID(extension.get(), "id3");
+  MenuItem::Id item1_id = item1->id();
+  MenuItem::Id item2_id = item2->id();
+  MenuItem::Id item3_id = item3->id();
+  ASSERT_TRUE(manager_.AddContextItem(extension.get(), std::move(item1)));
+  ASSERT_TRUE(manager_.AddContextItem(extension.get(), std::move(item2)));
+  ASSERT_TRUE(manager_.AddChildItem(item1_id, std::move(item3)));
+
+  // Verify that a write did or did not occur. For the non-persistent
+  // cases, remove the menus so we can test that they are properly
+  // restored from storage.
+  manager_.WriteToStorage(extension.get(), extension_key);
+  if (IsPersistent()) {
+    EXPECT_FALSE(observer.will_write_for_extension(extension->id()));
+  } else {
+    EXPECT_TRUE(observer.will_write_for_extension(extension->id()));
+    manager_.RemoveAllContextItems(extension_key);
+    EXPECT_FALSE(manager_.GetItemById(item1_id));
+    EXPECT_FALSE(manager_.GetItemById(item2_id));
+    EXPECT_FALSE(manager_.GetItemById(item3_id));
+  }
+
+  // Call MenuManager::OnExtensionLoaded(), which is where
+  // MenuManager::ReadFromStorage() is called, then flush the
+  // pending tasks in the StateStore. After that, we can check
+  // if a read occurred.
+  manager_.OnExtensionLoaded(profile_.get(), extension.get());
+  FlushStateStore();
+
+  if (IsPersistent()) {
+    EXPECT_FALSE(observer.did_read_for_extension(extension->id()));
+  } else {
+    EXPECT_TRUE(observer.did_read_for_extension(extension->id()));
+  }
+
+  // Expect the items to exist, either because we never cleared them
+  // or because they were reloaded from the store.
+  EXPECT_TRUE(manager_.GetItemById(item1_id));
+  EXPECT_TRUE(manager_.GetItemById(item2_id));
+  EXPECT_TRUE(manager_.GetItemById(item3_id));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc
index f2b609d..5712635 100644
--- a/chrome/browser/extensions/test_extension_prefs.cc
+++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -143,21 +143,17 @@
 
 scoped_refptr<Extension> TestExtensionPrefs::AddApp(const std::string& name) {
   base::DictionaryValue dictionary;
-  dictionary.SetString(manifest_keys::kName, name);
-  dictionary.SetString(manifest_keys::kVersion, "0.1");
+  AddDefaultManifestKeys(name, &dictionary);
   dictionary.SetString(manifest_keys::kApp, "true");
   dictionary.SetString(manifest_keys::kLaunchWebURL, "http://example.com");
   return AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
-
 }
 
 scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithLocation(
     const std::string& name,
     Manifest::Location location) {
   base::DictionaryValue dictionary;
-  dictionary.SetString(manifest_keys::kName, name);
-  dictionary.SetString(manifest_keys::kVersion, "0.1");
-  dictionary.SetInteger(manifest_keys::kManifestVersion, 2);
+  AddDefaultManifestKeys(name, &dictionary);
   return AddExtensionWithManifest(dictionary, location);
 }
 
@@ -218,4 +214,12 @@
       ExtensionSystem::Get(&profile_)->app_sorting());
 }
 
+void TestExtensionPrefs::AddDefaultManifestKeys(const std::string& name,
+                                                base::DictionaryValue* dict) {
+  DCHECK(dict);
+  dict->SetString(manifest_keys::kName, name);
+  dict->SetString(manifest_keys::kVersion, "0.1");
+  dict->SetInteger(manifest_keys::kManifestVersion, 2);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/test_extension_prefs.h b/chrome/browser/extensions/test_extension_prefs.h
index 8860402..87a73c7e 100644
--- a/chrome/browser/extensions/test_extension_prefs.h
+++ b/chrome/browser/extensions/test_extension_prefs.h
@@ -99,6 +99,9 @@
 
   ChromeAppSorting* app_sorting();
 
+  static void AddDefaultManifestKeys(const std::string& name,
+                                     base::DictionaryValue* dict);
+
  protected:
   class IncrementalClock;
 
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index ce9d619..7c0d10e9 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -43,6 +43,10 @@
 TestExtensionSystem::TestExtensionSystem(Profile* profile)
     : profile_(profile),
       store_factory_(new TestValueStoreFactory()),
+      state_store_(new StateStore(profile_,
+                                  store_factory_,
+                                  ValueStoreFrontend::BackendType::RULES,
+                                  false)),
       info_map_(new InfoMap()),
       quota_service_(new QuotaService()),
       app_sorting_(new ChromeAppSorting(profile_)) {
@@ -65,8 +69,6 @@
     const base::FilePath& install_directory,
     bool autoupdate_enabled,
     bool extensions_enabled) {
-  state_store_.reset(new StateStore(
-      profile_, store_factory_, ValueStoreFrontend::BackendType::RULES, false));
   management_policy_.reset(new ManagementPolicy());
   management_policy_->RegisterProviders(
       ExtensionManagementFactory::GetForBrowserContext(profile_)
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index 6d08f52..79c0839 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -97,8 +97,9 @@
   Profile* profile_;
 
  private:
-  std::unique_ptr<StateStore> state_store_;
   scoped_refptr<TestValueStoreFactory> store_factory_;
+  // This depends on store_factory_.
+  std::unique_ptr<StateStore> state_store_;
   std::unique_ptr<ManagementPolicy> management_policy_;
   std::unique_ptr<RuntimeData> runtime_data_;
   std::unique_ptr<ExtensionService> extension_service_;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index fe7067fd..09a951e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3876,7 +3876,7 @@
       "xinghuilu",
       "chrome-safebrowsing-core@google.com"
     ],
-    "expiry_milestone": 89
+    "expiry_milestone": 90
   },
   {
     "name": "privacy-sandbox-settings",
@@ -4085,7 +4085,7 @@
       "xinghuilu",
       "chrome-safebrowsing-core@google.com"
     ],
-    "expiry_milestone": 88
+    "expiry_milestone": 90
   },
   {
     "name": "safe-browsing-enhanced-protection-message-in-interstitials",
@@ -4113,7 +4113,7 @@
       "xinghuilu",
       "chrome-safebrowsing-core@google.com"
     ],
-    "expiry_milestone": 88
+    "expiry_milestone": 90
   },
   {
     "name": "safety-check-android",
diff --git a/chrome/browser/lacros/lacros_chrome_service_delegate_impl_unittest.cc b/chrome/browser/lacros/lacros_chrome_service_delegate_impl_unittest.cc
index 7c324be..827d5b3 100644
--- a/chrome/browser/lacros/lacros_chrome_service_delegate_impl_unittest.cc
+++ b/chrome/browser/lacros/lacros_chrome_service_delegate_impl_unittest.cc
@@ -6,30 +6,14 @@
 
 #include "base/files/file_path.h"
 #include "base/path_service.h"
-#include "base/system/sys_info.h"
 #include "base/test/scoped_path_override.h"
+#include "base/test/scoped_running_on_chromeos.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/crosapi/mojom/crosapi.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-const char kLsbRelease[] =
-    "CHROMEOS_RELEASE_NAME=Chrome OS\n"
-    "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
-
-// Overrides base::SysInfo::IsRunningOnChromeOS() to return true.
-// TODO(jamescook): Switch to the shared helper once crrev.com/c/2538285 lands.
-class ScopedIsRunningOnChromeOS {
- public:
-  ScopedIsRunningOnChromeOS() {
-    base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-  }
-  ~ScopedIsRunningOnChromeOS() {
-    base::SysInfo::SetChromeOSVersionInfoForTest("", base::Time());
-  }
-};
-
 class LacrosChromeServiceDelegateImplTest : public testing::Test {
  public:
   LacrosChromeServiceDelegateImplTest() = default;
@@ -40,7 +24,7 @@
   ~LacrosChromeServiceDelegateImplTest() override = default;
 
  private:
-  ScopedIsRunningOnChromeOS running_on_chromeos_;
+  base::test::ScopedRunningOnChromeOS running_on_chromeos_;
   // Ensure we restore the previous paths for subsequent tests. We don't
   // actually use these paths, so just point them at /tmp to avoid
   // ScopedPathOverride from creating unnecessary temp directories.
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.cc b/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.cc
index cbf28f6..5fda797 100644
--- a/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.cc
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.cc
@@ -18,17 +18,12 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/common/channel_info.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/signin/public/identity_manager/access_token_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
-#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
 #include "components/signin/public/identity_manager/scope_set.h"
-#include "components/version_info/version_info.h"
 #include "content/public/browser/storage_partition.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/google_api_keys.h"
 #include "media/base/media_switches.h"
 
 namespace {
@@ -43,9 +38,6 @@
 // The maximum number of feed items to display.
 constexpr int kMediaFeedsItemsMaxCount = 20;
 
-constexpr char kChromeMediaRecommendationsOAuth2Scope[] =
-    "https://www.googleapis.com/auth/chrome-media-recommendations";
-
 // The minimum watch time needed in media history for a provider to be
 // considered high watch time.
 constexpr base::TimeDelta kProviderHighWatchTimeMin =
@@ -73,71 +65,16 @@
     mojo::PendingReceiver<media::mojom::KaleidoscopeDataProvider> receiver,
     Profile* profile,
     KaleidoscopeMetricsRecorder* metrics_recorder)
-    : credentials_(media::mojom::Credentials::New()),
-      profile_(profile),
+    : profile_(profile),
       metrics_recorder_(metrics_recorder),
       receiver_(this, std::move(receiver)) {
   DCHECK(profile);
 
-  // If this is Google Chrome then we should use the official API key.
-  if (google_apis::IsGoogleChromeAPIKeyUsed()) {
-    bool is_stable_channel =
-        chrome::GetChannel() == version_info::Channel::STABLE;
-    credentials_->api_key = is_stable_channel
-                                ? google_apis::GetAPIKey()
-                                : google_apis::GetNonStableAPIKey();
-  }
-
-  identity_manager_ = IdentityManagerFactory::GetForProfile(profile);
+  identity_manager_ = IdentityManagerFactory::GetForProfile(profile_);
 }
 
 KaleidoscopeDataProviderImpl::~KaleidoscopeDataProviderImpl() = default;
 
-void KaleidoscopeDataProviderImpl::GetCredentials(GetCredentialsCallback cb) {
-  // If the profile is incognito then disable Kaleidoscope.
-  if (profile_->IsOffTheRecord()) {
-    std::move(cb).Run(nullptr,
-                      media::mojom::CredentialsResult::kFailedIncognito);
-    return;
-  }
-
-  // If the profile is a child then disable Kaleidoscope.
-  if (profile_->IsSupervised() || profile_->IsChild()) {
-    std::move(cb).Run(nullptr, media::mojom::CredentialsResult::kFailedChild);
-    return;
-  }
-
-  // If the administrator has disabled Kaleidoscope then stop.
-  auto* prefs = profile_->GetPrefs();
-  if (!prefs->GetBoolean(kaleidoscope::prefs::kKaleidoscopePolicyEnabled)) {
-    std::move(cb).Run(nullptr,
-                      media::mojom::CredentialsResult::kDisabledByPolicy);
-    return;
-  }
-
-  // If the user is not signed in, return the credentials without an access
-  // token. Sync consent is not required to use Kaleidoscope.
-  if (!identity_manager_->HasPrimaryAccount(
-          signin::ConsentLevel::kNotRequired)) {
-    std::move(cb).Run(credentials_.Clone(),
-                      media::mojom::CredentialsResult::kSuccess);
-    return;
-  }
-
-  pending_callbacks_.push_back(std::move(cb));
-
-  // Get an OAuth token for the backend API. This token will be limited to just
-  // our backend scope. Destroying |token_fetcher_| will cancel the fetch so
-  // unretained is safe here.
-  signin::ScopeSet scopes = {kChromeMediaRecommendationsOAuth2Scope};
-  token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
-      "kaleidoscope_service", identity_manager_, scopes,
-      base::BindOnce(&KaleidoscopeDataProviderImpl::OnAccessTokenAvailable,
-                     base::Unretained(this)),
-      signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate,
-      signin::ConsentLevel::kNotRequired);
-}
-
 void KaleidoscopeDataProviderImpl::GetShouldShowFirstRunExperience(
     GetShouldShowFirstRunExperienceCallback cb) {
   auto* service = kaleidoscope::KaleidoscopeService::Get(profile_);
@@ -278,11 +215,15 @@
                            std::string() /* extra_diagnostics */);
 }
 
-void KaleidoscopeDataProviderImpl::GetCollections(const std::string& request,
-                                                  GetCollectionsCallback cb) {
-  GetCredentials(base::BindOnce(
-      &KaleidoscopeDataProviderImpl::OnGotCredentialsForCollections,
-      weak_ptr_factory.GetWeakPtr(), request, std::move(cb)));
+void KaleidoscopeDataProviderImpl::GetCollections(
+    media::mojom::CredentialsPtr credentials,
+    const std::string& request,
+    GetCollectionsCallback cb) {
+  auto account_info = identity_manager_->GetPrimaryAccountInfo(
+      signin::ConsentLevel::kNotRequired);
+
+  kaleidoscope::KaleidoscopeService::Get(profile_)->GetCollections(
+      std::move(credentials), account_info.gaia, request, std::move(cb));
 }
 
 void KaleidoscopeDataProviderImpl::GetSignedOutProviders(
@@ -320,50 +261,12 @@
                                 time);
 }
 
-void KaleidoscopeDataProviderImpl::OnGotCredentialsForCollections(
-    const std::string& request,
-    GetCollectionsCallback cb,
-    media::mojom::CredentialsPtr credentials,
-    media::mojom::CredentialsResult result) {
-  // If we have no credentials then we should return an empty response.
-  if (result != media::mojom::CredentialsResult::kSuccess) {
-    std::move(cb).Run(media::mojom::GetCollectionsResponse::New(
-        "", media::mojom::GetCollectionsResult::kFailed));
-    return;
-  }
-
-  auto account_info = identity_manager_->GetPrimaryAccountInfo(
-      signin::ConsentLevel::kNotRequired);
-
-  kaleidoscope::KaleidoscopeService::Get(profile_)->GetCollections(
-      std::move(credentials), account_info.gaia, request, std::move(cb));
-}
-
 media_history::MediaHistoryKeyedService*
 KaleidoscopeDataProviderImpl::GetMediaHistoryService() {
   return media_history::MediaHistoryKeyedServiceFactory::GetForProfile(
       profile_);
 }
 
-void KaleidoscopeDataProviderImpl::OnAccessTokenAvailable(
-    GoogleServiceAuthError error,
-    signin::AccessTokenInfo access_token_info) {
-  DCHECK(token_fetcher_);
-  token_fetcher_.reset();
-
-  if (error.state() == GoogleServiceAuthError::State::NONE) {
-    credentials_->access_token = access_token_info.token;
-    credentials_->expiry_time = access_token_info.expiration_time;
-  }
-
-  for (auto& callback : pending_callbacks_) {
-    std::move(callback).Run(credentials_.Clone(),
-                            media::mojom::CredentialsResult::kSuccess);
-  }
-
-  pending_callbacks_.clear();
-}
-
 void KaleidoscopeDataProviderImpl::OnGotMediaFeedContents(
     GetMediaFeedContentsCallback callback,
     const int64_t feed_id,
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h b/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h
index e5c885b..d6ee48d 100644
--- a/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h
@@ -19,9 +19,7 @@
 }  // namespace media_history
 
 namespace signin {
-struct AccessTokenInfo;
 class IdentityManager;
-class PrimaryAccountAccessTokenFetcher;
 }  // namespace signin
 
 class KaleidoscopeMetricsRecorder;
@@ -34,6 +32,7 @@
       mojo::PendingReceiver<media::mojom::KaleidoscopeDataProvider> receiver,
       Profile* profile,
       KaleidoscopeMetricsRecorder* metrics_recorder);
+
   KaleidoscopeDataProviderImpl(const KaleidoscopeDataProviderImpl&) = delete;
   KaleidoscopeDataProviderImpl& operator=(const KaleidoscopeDataProviderImpl&) =
       delete;
@@ -48,7 +47,6 @@
   void GetContinueWatchingMediaFeedItems(
       media::mojom::KaleidoscopeTab tab,
       GetContinueWatchingMediaFeedItemsCallback callback) override;
-  void GetCredentials(GetCredentialsCallback cb) override;
   void GetShouldShowFirstRunExperience(
       GetShouldShowFirstRunExperienceCallback cb) override;
   void SetFirstRunExperienceStep(
@@ -63,7 +61,8 @@
       GetAutoSelectMediaFeedsConsentCallback cb) override;
   void GetHighWatchTimeOrigins(GetHighWatchTimeOriginsCallback cb) override;
   void SendFeedback() override;
-  void GetCollections(const std::string& request,
+  void GetCollections(media::mojom::CredentialsPtr credentials,
+                      const std::string& request,
                       GetCollectionsCallback cb) override;
   void GetSignedOutProviders(GetSignedOutProvidersCallback cb) override;
   void SetSignedOutProviders(
@@ -73,15 +72,6 @@
  private:
   media_history::MediaHistoryKeyedService* GetMediaHistoryService();
 
-  void OnGotCredentialsForCollections(const std::string& request,
-                                      GetCollectionsCallback cb,
-                                      media::mojom::CredentialsPtr credentials,
-                                      media::mojom::CredentialsResult result);
-
-  // Called when an access token request completes (successfully or not).
-  void OnAccessTokenAvailable(GoogleServiceAuthError error,
-                              signin::AccessTokenInfo access_token_info);
-
   void OnGotMediaFeedContents(
       GetMediaFeedContentsCallback callback,
       const int64_t feed_id,
@@ -90,16 +80,6 @@
       GetContinueWatchingMediaFeedItemsCallback callback,
       std::vector<media_feeds::mojom::MediaFeedItemPtr> items);
 
-  // Helper for fetching OAuth2 access tokens. This is non-null iff an access
-  // token request is currently in progress.
-  std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_;
-
-  // The current set of credentials.
-  media::mojom::CredentialsPtr credentials_;
-
-  // Pending credentials waiting on an access token.
-  std::vector<GetCredentialsCallback> pending_callbacks_;
-
   signin::IdentityManager* identity_manager_;
 
   Profile* const profile_;
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.cc b/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.cc
new file mode 100644
index 0000000..4cda574
--- /dev/null
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.cc
@@ -0,0 +1,120 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h"
+
+#include "base/callback.h"
+#include "chrome/browser/media/kaleidoscope/kaleidoscope_prefs.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/common/channel_info.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+#include "components/version_info/version_info.h"
+#include "google_apis/google_api_keys.h"
+
+namespace {
+
+constexpr char kChromeMediaRecommendationsOAuth2Scope[] =
+    "https://www.googleapis.com/auth/chrome-media-recommendations";
+
+}  // namespace
+
+KaleidoscopeIdentityManagerImpl::KaleidoscopeIdentityManagerImpl(
+    mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager> receiver,
+    content::WebUI* web_ui)
+    : KaleidoscopeIdentityManagerImpl(std::move(receiver),
+                                      Profile::FromWebUI(web_ui)) {
+  DCHECK(web_ui);
+  web_ui_ = web_ui;
+}
+
+KaleidoscopeIdentityManagerImpl::KaleidoscopeIdentityManagerImpl(
+    mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager> receiver,
+    Profile* profile)
+    : credentials_(media::mojom::Credentials::New()),
+      profile_(profile),
+      receiver_(this, std::move(receiver)) {
+  DCHECK(profile);
+
+  // If this is Google Chrome then we should use the official API key.
+  if (google_apis::IsGoogleChromeAPIKeyUsed()) {
+    bool is_stable_channel =
+        chrome::GetChannel() == version_info::Channel::STABLE;
+    credentials_->api_key = is_stable_channel
+                                ? google_apis::GetAPIKey()
+                                : google_apis::GetNonStableAPIKey();
+  }
+
+  identity_manager_ = IdentityManagerFactory::GetForProfile(profile);
+}
+
+KaleidoscopeIdentityManagerImpl::~KaleidoscopeIdentityManagerImpl() = default;
+
+void KaleidoscopeIdentityManagerImpl::GetCredentials(
+    GetCredentialsCallback cb) {
+  // If the profile is incognito then disable Kaleidoscope.
+  if (profile_->IsOffTheRecord()) {
+    std::move(cb).Run(nullptr,
+                      media::mojom::CredentialsResult::kFailedIncognito);
+    return;
+  }
+
+  // If the profile is a child then disable Kaleidoscope.
+  if (profile_->IsSupervised() || profile_->IsChild()) {
+    std::move(cb).Run(nullptr, media::mojom::CredentialsResult::kFailedChild);
+    return;
+  }
+
+  // If the administrator has disabled Kaleidoscope then stop.
+  auto* prefs = profile_->GetPrefs();
+  if (!prefs->GetBoolean(kaleidoscope::prefs::kKaleidoscopePolicyEnabled)) {
+    std::move(cb).Run(nullptr,
+                      media::mojom::CredentialsResult::kDisabledByPolicy);
+    return;
+  }
+
+  // If the user is not signed in, return the credentials without an access
+  // token. Sync consent is not required to use Kaleidoscope.
+  if (!identity_manager_->HasPrimaryAccount(
+          signin::ConsentLevel::kNotRequired)) {
+    std::move(cb).Run(credentials_.Clone(),
+                      media::mojom::CredentialsResult::kSuccess);
+    return;
+  }
+
+  pending_callbacks_.push_back(std::move(cb));
+
+  // Get an OAuth token for the backend API. This token will be limited to just
+  // our backend scope. Destroying |token_fetcher_| will cancel the fetch so
+  // unretained is safe here.
+  signin::ScopeSet scopes = {kChromeMediaRecommendationsOAuth2Scope};
+  token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
+      "kaleidoscope_service", identity_manager_, scopes,
+      base::BindOnce(&KaleidoscopeIdentityManagerImpl::OnAccessTokenAvailable,
+                     base::Unretained(this)),
+      signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate,
+      signin::ConsentLevel::kNotRequired);
+}
+
+void KaleidoscopeIdentityManagerImpl::OnAccessTokenAvailable(
+    GoogleServiceAuthError error,
+    signin::AccessTokenInfo access_token_info) {
+  DCHECK(token_fetcher_);
+  token_fetcher_.reset();
+
+  if (error.state() == GoogleServiceAuthError::State::NONE) {
+    credentials_->access_token = access_token_info.token;
+    credentials_->expiry_time = access_token_info.expiration_time;
+  }
+
+  for (auto& callback : pending_callbacks_) {
+    std::move(callback).Run(credentials_.Clone(),
+                            media::mojom::CredentialsResult::kSuccess);
+  }
+
+  pending_callbacks_.clear();
+}
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h b/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h
new file mode 100644
index 0000000..9743bbcd
--- /dev/null
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h
@@ -0,0 +1,69 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_KALEIDOSCOPE_KALEIDOSCOPE_IDENTITY_MANAGER_IMPL_H_
+#define CHROME_BROWSER_MEDIA_KALEIDOSCOPE_KALEIDOSCOPE_IDENTITY_MANAGER_IMPL_H_
+
+#include <memory>
+
+#include "chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace content {
+class WebUI;
+}  //  namespace content
+
+namespace signin {
+struct AccessTokenInfo;
+class IdentityManager;
+class PrimaryAccountAccessTokenFetcher;
+}  // namespace signin
+
+class Profile;
+
+class KaleidoscopeIdentityManagerImpl
+    : public media::mojom::KaleidoscopeIdentityManager {
+ public:
+  KaleidoscopeIdentityManagerImpl(
+      mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager> receiver,
+      content::WebUI* web_ui);
+  KaleidoscopeIdentityManagerImpl(
+      mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager> receiver,
+      Profile* profile);
+
+  KaleidoscopeIdentityManagerImpl(const KaleidoscopeIdentityManagerImpl&) =
+      delete;
+  KaleidoscopeIdentityManagerImpl& operator=(
+      const KaleidoscopeIdentityManagerImpl&) = delete;
+  ~KaleidoscopeIdentityManagerImpl() override;
+
+  // media::mojom::KaleidoscopeIdentityManager implementation.
+  void GetCredentials(GetCredentialsCallback cb) override;
+
+ private:
+  // Called when an access token request completes (successfully or not).
+  void OnAccessTokenAvailable(GoogleServiceAuthError error,
+                              signin::AccessTokenInfo access_token_info);
+
+  // Helper for fetching OAuth2 access tokens. This is non-null iff an access
+  // token request is currently in progress.
+  std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_;
+
+  // Pending credentials waiting on an access token.
+  std::vector<GetCredentialsCallback> pending_callbacks_;
+
+  // The current set of credentials.
+  media::mojom::CredentialsPtr credentials_;
+
+  signin::IdentityManager* identity_manager_;
+
+  content::WebUI* web_ui_ = nullptr;
+  Profile* profile_ = nullptr;
+
+  mojo::Receiver<media::mojom::KaleidoscopeIdentityManager> receiver_;
+};
+
+#endif  // CHROME_BROWSER_MEDIA_KALEIDOSCOPE_KALEIDOSCOPE_IDENTITY_MANAGER_IMPL_H_
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_ui.cc b/chrome/browser/media/kaleidoscope/kaleidoscope_ui.cc
index 36c2100..5defbf9 100644
--- a/chrome/browser/media/kaleidoscope/kaleidoscope_ui.cc
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_ui.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/media/kaleidoscope/constants.h"
 #include "chrome/browser/media/kaleidoscope/grit/kaleidoscope_resources.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h"
+#include "chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_metrics_recorder.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_switches.h"
 #include "chrome/browser/profiles/profile.h"
@@ -246,6 +247,7 @@
   // provider has a pointer to the metrics recorder.
   provider_.reset();
   metrics_recorder_.reset();
+  identity_manager_.reset();
 }
 
 // static
@@ -393,4 +395,11 @@
       metrics_recorder_.get());
 }
 
+void KaleidoscopeUI::BindInterface(
+    mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager>
+        identity_manager) {
+  identity_manager_ = std::make_unique<KaleidoscopeIdentityManagerImpl>(
+      std::move(identity_manager), web_ui());
+}
+
 WEB_UI_CONTROLLER_TYPE_IMPL(KaleidoscopeUI)
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_ui.h b/chrome/browser/media/kaleidoscope/kaleidoscope_ui.h
index 6da3a6b..413edd7 100644
--- a/chrome/browser/media/kaleidoscope/kaleidoscope_ui.h
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_ui.h
@@ -24,6 +24,9 @@
 
   void BindInterface(
       mojo::PendingReceiver<media::mojom::KaleidoscopeDataProvider> provider);
+  void BindInterface(
+      mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager>
+          identity_manager);
 
   static content::WebUIDataSource* CreateWebUIDataSource();
 
@@ -32,6 +35,7 @@
  private:
   std::unique_ptr<KaleidoscopeMetricsRecorder> metrics_recorder_;
   std::unique_ptr<media::mojom::KaleidoscopeDataProvider> provider_;
+  std::unique_ptr<media::mojom::KaleidoscopeIdentityManager> identity_manager_;
 
   WEB_UI_CONTROLLER_TYPE_DECL();
 };
diff --git a/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom b/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom
index 456fd67..3937f7b0 100644
--- a/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom
+++ b/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom
@@ -60,9 +60,6 @@
   // continue watching. Returned items will be appropriate for the |tab|.
   GetContinueWatchingMediaFeedItems(KaleidoscopeTab tab) => (array<media_feeds.mojom.MediaFeedItem> items);
 
-  // Retrieves the current credentials.
-  GetCredentials() => (Credentials? credentials, CredentialsResult result);
-
   // Returns true if the first run experience should be shown.
   GetShouldShowFirstRunExperience() => (bool should_show_first_run);
 
@@ -92,10 +89,11 @@
   // Will trigger a feedback dialog to be displayed.
   SendFeedback();
 
-  // Gets the collections from the backend to be displayed. Takes a string that
-  // contains the request to be sent to the server. The request is the
-  // GetCollectionsRequest proto here: go/ks-media-proto.
-  GetCollections(string request) => (GetCollectionsResponse response);
+  // Gets the collections from the backend to be displayed. Takes a credential
+  // instance and a string that contains the request to be sent to the server.
+  // The request is the GetCollectionsRequest proto here: go/ks-media-proto.
+  GetCollections(Credentials credentials, string request)
+      => (GetCollectionsResponse response);
 
   // Gets a list of stored providers that will be used to filter the
   // recommendations on the server if the user is signed out. They are arbitary
@@ -111,6 +109,12 @@
   RecordTimeTakenToStartWatchHistogram(mojo_base.mojom.TimeDelta time);
 };
 
+// Handles identity related tasks.
+interface KaleidoscopeIdentityManager {
+  // Retrieves the current credentials.
+  GetCredentials() => (Credentials? credentials, CredentialsResult result);
+};
+
 enum GetCollectionsResult {
  // The request was successful.
  kSuccess,
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index c42c5cf..51b0562 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -166,6 +166,8 @@
     ]
     public_deps = [ ":router" ]
     sources = [
+      "providers/test/test_media_route_provider.cc",
+      "providers/test/test_media_route_provider.h",
       "test/media_router_mojo_test.cc",
       "test/media_router_mojo_test.h",
       "test/mock_dns_sd_registry.cc",
diff --git a/chrome/browser/media/router/providers/test/test_media_route_provider.cc b/chrome/browser/media/router/providers/test/test_media_route_provider.cc
new file mode 100644
index 0000000..95bc9cf
--- /dev/null
+++ b/chrome/browser/media/router/providers/test/test_media_route_provider.cc
@@ -0,0 +1,269 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/providers/test/test_media_route_provider.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/run_loop.h"
+#include "components/media_router/common/media_source.h"
+#include "components/media_router/common/mojom/media_router.mojom.h"
+#include "components/media_router/common/route_request_result.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace media_router {
+
+namespace {
+
+bool IsValidSource(const std::string& source_urn) {
+  return (source_urn.find("test:") == 0 ||
+          IsValidStandardPresentationSource(source_urn));
+}
+
+void Wait(base::TimeDelta timeout) {
+  base::RunLoop run_loop;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), timeout);
+  run_loop.Run();
+}
+
+}  // namespace
+
+const MediaRouteProviderId TestMediaRouteProvider::kProviderId =
+    MediaRouteProviderId::CAST;
+
+TestMediaRouteProvider::TestMediaRouteProvider(
+    mojo::PendingReceiver<mojom::MediaRouteProvider> receiver,
+    mojo::PendingRemote<mojom::MediaRouter> media_router)
+    : receiver_(this, std::move(receiver)),
+      media_router_(std::move(media_router)) {
+  SetSinks();
+  media_router_->OnSinkAvailabilityUpdated(
+      kProviderId, mojom::MediaRouter::SinkAvailability::PER_SOURCE);
+}
+
+void TestMediaRouteProvider::SetSinks() {
+  MediaSinkInternal sink_internal_1;
+  MediaSinkInternal sink_internal_2;
+  sink_internal_1.set_sink(MediaSink("id1", "test-sink-1", SinkIconType::CAST));
+  sink_internal_2.set_sink(MediaSink("id2", "test-sink-2", SinkIconType::CAST));
+  sinks_ = {sink_internal_1, sink_internal_2};
+}
+
+void TestMediaRouteProvider::CreateRoute(const std::string& media_source,
+                                         const std::string& sink_id,
+                                         const std::string& presentation_id,
+                                         const url::Origin& origin,
+                                         int32_t tab_id,
+                                         base::TimeDelta timeout,
+                                         bool incognito,
+                                         CreateRouteCallback callback) {
+  if (!route_error_message_.empty()) {
+    std::move(callback).Run(base::nullopt, nullptr, route_error_message_,
+                            RouteRequestResult::ResultCode::UNKNOWN_ERROR);
+  } else {
+    if (delay_ms_ > 0)
+      Wait(base::TimeDelta::FromMilliseconds(delay_ms_));
+    DVLOG(2) << "CreateRoute with origin: " << origin << " and tab ID "
+             << tab_id;
+    MediaRoute route(presentation_id, MediaSource(media_source), sink_id,
+                     std::string("Test Route"), true, true);
+    route.set_controller_type(RouteControllerType::kGeneric);
+    route.set_off_the_record(incognito);
+    const std::string& route_id = route.media_route_id();
+    routes_[route_id] = route;
+    presentation_ids_to_routes_[presentation_id] = route;
+
+    media_router_->OnPresentationConnectionStateChanged(
+        route_id, blink::mojom::PresentationConnectionState::CONNECTED);
+    media_router_->OnRoutesUpdated(kProviderId, GetMediaRoutes(), media_source,
+                                   {});
+
+    std::move(callback).Run(route, nullptr, base::nullopt,
+                            RouteRequestResult::UNKNOWN_ERROR);
+  }
+}
+
+void TestMediaRouteProvider::JoinRoute(const std::string& media_source,
+                                       const std::string& presentation_id,
+                                       const url::Origin& origin,
+                                       int32_t tab_id,
+                                       base::TimeDelta timeout,
+                                       bool incognito,
+                                       JoinRouteCallback callback) {
+  if (!route_error_message_.empty()) {
+    std::move(callback).Run(base::nullopt, nullptr, route_error_message_,
+                            RouteRequestResult::UNKNOWN_ERROR);
+    return;
+  }
+  if (!IsValidSource(media_source)) {
+    std::move(callback).Run(base::nullopt, nullptr,
+                            std::string("The media source is invalid."),
+                            RouteRequestResult::UNKNOWN_ERROR);
+    return;
+  }
+  auto pos = presentation_ids_to_routes_.find(presentation_id);
+  if (pos == presentation_ids_to_routes_.end()) {
+    std::move(callback).Run(base::nullopt, nullptr,
+                            std::string("Presentation does not exist."),
+                            RouteRequestResult::UNKNOWN_ERROR);
+  } else if (pos->second.is_off_the_record() != incognito) {
+    std::move(callback).Run(base::nullopt, nullptr,
+                            std::string("Off-the-record mismatch."),
+                            RouteRequestResult::UNKNOWN_ERROR);
+  } else {
+    MediaRoute& existing_route = pos->second;
+    std::move(callback).Run(existing_route, nullptr,
+                            std::string("Successfully joined session"),
+                            RouteRequestResult::ResultCode::OK);
+  }
+}
+
+void TestMediaRouteProvider::ConnectRouteByRouteId(
+    const std::string& media_source,
+    const std::string& route_id,
+    const std::string& presentation_id,
+    const url::Origin& origin,
+    int32_t tab_id,
+    base::TimeDelta timeout,
+    bool incognito,
+    ConnectRouteByRouteIdCallback callback) {
+  if (!IsValidSource(media_source)) {
+    std::move(callback).Run(base::nullopt, nullptr,
+                            std::string("The media source is invalid."),
+                            RouteRequestResult::UNKNOWN_ERROR);
+    return;
+  }
+  auto pos = routes_.find(route_id);
+  if (pos == presentation_ids_to_routes_.end()) {
+    std::move(callback).Run(base::nullopt, nullptr,
+                            std::string("Presentation does not exist."),
+                            RouteRequestResult::UNKNOWN_ERROR);
+  } else {
+    MediaRoute& existing_route = pos->second;
+    std::move(callback).Run(existing_route, nullptr,
+                            std::string("Connect route by route ID"),
+                            RouteRequestResult::ResultCode::OK);
+  }
+}
+
+void TestMediaRouteProvider::TerminateRoute(const std::string& route_id,
+                                            TerminateRouteCallback callback) {
+  auto it = routes_.find(route_id);
+  if (it == routes_.end()) {
+    std::move(callback).Run(std::string("Route not found in test provider"),
+                            RouteRequestResult::ROUTE_NOT_FOUND);
+    return;
+  }
+  presentation_ids_to_routes_.erase(it->second.presentation_id());
+  routes_.erase(it);
+  media_router_->OnPresentationConnectionStateChanged(
+      route_id, blink::mojom::PresentationConnectionState::TERMINATED);
+  media_router_->OnRoutesUpdated(
+      kProviderId, GetMediaRoutes(),
+      MediaRoute::GetMediaSourceIdFromMediaRouteId(route_id), {});
+  std::move(callback).Run(base::nullopt, RouteRequestResult::OK);
+}
+
+void TestMediaRouteProvider::SendRouteMessage(const std::string& media_route_id,
+                                              const std::string& message) {
+  if (close_route_with_error_on_send_) {
+    auto it = routes_.find(media_route_id);
+    presentation_ids_to_routes_.erase(it->second.presentation_id());
+    routes_.erase(it);
+    media_router_->OnPresentationConnectionClosed(
+        media_route_id,
+        blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR,
+        "Send error. Closing connection.");
+    media_router_->OnRoutesUpdated(
+        kProviderId, GetMediaRoutes(),
+        MediaRoute::GetMediaSourceIdFromMediaRouteId(media_route_id), {});
+  } else {
+    std::string response = "Pong: " + message;
+    std::vector<mojom::RouteMessagePtr> messages;
+    messages.emplace_back(mojom::RouteMessage::New(
+        mojom::RouteMessage::Type::TEXT, response, base::nullopt));
+    media_router_->OnRouteMessagesReceived(media_route_id, std::move(messages));
+  }
+}
+
+void TestMediaRouteProvider::SendRouteBinaryMessage(
+    const std::string& media_route_id,
+    const std::vector<uint8_t>& data) {
+  NOTREACHED() << "Route " << media_route_id
+               << " does not support sending binary data.";
+}
+
+void TestMediaRouteProvider::StartObservingMediaSinks(
+    const std::string& media_source) {
+  media_router_->OnSinksReceived(kProviderId, media_source, sinks_, {});
+}
+
+void TestMediaRouteProvider::StopObservingMediaSinks(
+    const std::string& media_source) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::StartObservingMediaRoutes(
+    const std::string& media_source) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::StopObservingMediaRoutes(
+    const std::string& media_source) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::StartListeningForRouteMessages(
+    const std::string& route_id) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::StopListeningForRouteMessages(
+    const std::string& route_id) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::DetachRoute(const std::string& route_id) {
+  media_router_->OnPresentationConnectionClosed(
+      route_id, blink::mojom::PresentationConnectionCloseReason::CLOSED,
+      "Close route");
+}
+
+void TestMediaRouteProvider::EnableMdnsDiscovery() {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::UpdateMediaSinks(const std::string& media_source) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::CreateMediaRouteController(
+    const std::string& route_id,
+    mojo::PendingReceiver<mojom::MediaController> media_controller,
+    mojo::PendingRemote<mojom::MediaStatusObserver> observer,
+    CreateMediaRouteControllerCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void TestMediaRouteProvider::ProvideSinks(
+    const std::string& provider_name,
+    const std::vector<media_router::MediaSinkInternal>& sinks) {
+  NOTIMPLEMENTED();
+}
+
+std::vector<MediaRoute> TestMediaRouteProvider::GetMediaRoutes() {
+  std::vector<MediaRoute> route_list;
+  for (const auto& route : routes_)
+    route_list.push_back(route.second);
+  return route_list;
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/providers/test/test_media_route_provider.h b/chrome/browser/media/router/providers/test/test_media_route_provider.h
new file mode 100644
index 0000000..6a3f274
--- /dev/null
+++ b/chrome/browser/media/router/providers/test/test_media_route_provider.h
@@ -0,0 +1,105 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_TEST_TEST_MEDIA_ROUTE_PROVIDER_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_TEST_TEST_MEDIA_ROUTE_PROVIDER_H_
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "components/media_router/common/media_route.h"
+#include "components/media_router/common/mojom/media_router.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace media_router {
+
+// The Test MediaRouteProvider class is used for integration browser test.
+class TestMediaRouteProvider : public mojom::MediaRouteProvider {
+ public:
+  static const MediaRouteProviderId kProviderId;
+  TestMediaRouteProvider(
+      mojo::PendingReceiver<mojom::MediaRouteProvider> receiver,
+      mojo::PendingRemote<mojom::MediaRouter> media_router);
+  ~TestMediaRouteProvider() override;
+
+  void CreateRoute(const std::string& media_source,
+                   const std::string& sink_id,
+                   const std::string& presentation_id,
+                   const url::Origin& origin,
+                   int32_t tab_id,
+                   base::TimeDelta timeout,
+                   bool incognito,
+                   CreateRouteCallback callback) override;
+  void JoinRoute(const std::string& media_source,
+                 const std::string& presentation_id,
+                 const url::Origin& origin,
+                 int32_t tab_id,
+                 base::TimeDelta timeout,
+                 bool incognito,
+                 JoinRouteCallback callback) override;
+  void ConnectRouteByRouteId(const std::string& media_source,
+                             const std::string& route_id,
+                             const std::string& presentation_id,
+                             const url::Origin& origin,
+                             int32_t tab_id,
+                             base::TimeDelta timeout,
+                             bool incognito,
+                             ConnectRouteByRouteIdCallback callback) override;
+  void TerminateRoute(const std::string& route_id,
+                      TerminateRouteCallback callback) override;
+  void SendRouteMessage(const std::string& media_route_id,
+                        const std::string& message) override;
+  void SendRouteBinaryMessage(const std::string& media_route_id,
+                              const std::vector<uint8_t>& data) override;
+  void StartObservingMediaSinks(const std::string& media_source) override;
+  void StopObservingMediaSinks(const std::string& media_source) override;
+  void StartObservingMediaRoutes(const std::string& media_source) override;
+  void StopObservingMediaRoutes(const std::string& media_source) override;
+  void StartListeningForRouteMessages(const std::string& route_id) override;
+  void StopListeningForRouteMessages(const std::string& route_id) override;
+  void DetachRoute(const std::string& route_id) override;
+  void EnableMdnsDiscovery() override;
+  void UpdateMediaSinks(const std::string& media_source) override;
+  void CreateMediaRouteController(
+      const std::string& route_id,
+      mojo::PendingReceiver<mojom::MediaController> media_controller,
+      mojo::PendingRemote<mojom::MediaStatusObserver> observer,
+      CreateMediaRouteControllerCallback callback) override;
+  void ProvideSinks(
+      const std::string& provider_name,
+      const std::vector<media_router::MediaSinkInternal>& sinks) override;
+
+ private:
+  void set_close_route_error_on_send() {
+    close_route_with_error_on_send_ = true;
+  }
+  void set_delay_ms(int delay_ms) { delay_ms_ = delay_ms; }
+  void set_route_error_message(std::string error_message) {
+    route_error_message_ = error_message;
+  }
+  std::vector<MediaRoute> GetMediaRoutes();
+  void SetSinks();
+
+  bool close_route_with_error_on_send_ = false;
+  int delay_ms_ = 0;
+  std::string route_error_message_;
+  std::map<std::string, MediaRoute> presentation_ids_to_routes_;
+  std::map<MediaRoute::Id, MediaRoute> routes_;
+  std::vector<MediaSinkInternal> sinks_;
+
+  // Binds |this| to the Mojo receiver passed into the ctor.
+  mojo::Receiver<mojom::MediaRouteProvider> receiver_;
+  // Mojo remote to the Media Router.
+  mojo::Remote<mojom::MediaRouter> media_router_;
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_TEST_TEST_MEDIA_ROUTE_PROVIDER_H_
diff --git a/chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.cc b/chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.cc
index 17bd74e04..339dca3 100644
--- a/chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.cc
+++ b/chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.cc
@@ -28,13 +28,6 @@
 
 namespace {
 
-bool IsPresentationSource(const std::string& media_source) {
-  const GURL source_url(media_source);
-  return source_url.is_valid() && source_url.SchemeIsHTTPOrHTTPS() &&
-         !base::StartsWith(source_url.spec(), kLegacyCastPresentationUrlPrefix,
-                           base::CompareCase::INSENSITIVE_ASCII);
-}
-
 MediaSinkInternal CreateSinkForDisplay(const Display& display,
                                        int display_index) {
   const std::string sink_id =
@@ -201,7 +194,7 @@
 
 void WiredDisplayMediaRouteProvider::StartObservingMediaSinks(
     const std::string& media_source) {
-  if (!IsPresentationSource(media_source))
+  if (!IsValidStandardPresentationSource(media_source))
     return;
 
   // Start observing displays if |this| isn't already observing.
@@ -251,7 +244,7 @@
 
 void WiredDisplayMediaRouteProvider::UpdateMediaSinks(
     const std::string& media_source) {
-  if (IsPresentationSource(media_source))
+  if (IsValidStandardPresentationSource(media_source))
     media_router_->OnSinksReceived(kProviderId, media_source, GetSinks(), {});
 }
 
diff --git a/chrome/browser/metrics/BUILD.gn b/chrome/browser/metrics/BUILD.gn
index b4a3aad..564454e 100644
--- a/chrome/browser/metrics/BUILD.gn
+++ b/chrome/browser/metrics/BUILD.gn
@@ -13,6 +13,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//chrome/browser",
     "//components/signin/public/identity_manager",
     "//components/sync/test/fake_server",
diff --git a/chrome/browser/metrics/authenticator_utility.cc b/chrome/browser/metrics/authenticator_utility.cc
index af52d65..c3fd6a49 100644
--- a/chrome/browser/metrics/authenticator_utility.cc
+++ b/chrome/browser/metrics/authenticator_utility.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_functions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -86,7 +87,7 @@
   ReportAvailability(
       win_webauthn_api &&
       content::IsUVPlatformAuthenticatorAvailable(win_webauthn_api));
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   ReportAvailability(content::IsUVPlatformAuthenticatorAvailable());
 #endif
 }
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index e476958..2635827 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -50,7 +50,9 @@
 #include <cpu-features.h>
 #endif  // defined(OS_ANDROID) && defined(__arm__)
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include <gnu/libc-version.h>
 
 #include "base/linux_util.h"
@@ -61,7 +63,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/base/x/x11_util.h"
 #endif
-#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
 #if defined(USE_OZONE) || defined(USE_X11)
 #include "ui/events/devices/device_data_manager.h"
@@ -229,7 +231,9 @@
 #endif
 }
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 void RecordLinuxDistroSpecific(const std::string& version_string,
                                size_t parts,
                                const char* histogram_name) {
@@ -305,10 +309,12 @@
 
   base::UmaHistogramSparse("Linux.Distro2", distro_result);
 }
-#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
 void RecordLinuxGlibcVersion() {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   base::Version version(gnu_get_libc_version());
 
   UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
@@ -565,7 +571,9 @@
   constexpr base::TaskTraits kBestEffortTaskTraits = {
       base::MayBlock(), base::TaskPriority::BEST_EFFORT,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   base::ThreadPool::PostTask(FROM_HERE, kBestEffortTaskTraits,
                              base::BindOnce(&RecordLinuxDistro));
 #endif
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc
index 5b37e71..73fcd64 100644
--- a/chrome/browser/metrics/chrome_feature_list_creator.cc
+++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -16,6 +16,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/base/switches.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
@@ -44,10 +45,10 @@
 #include "content/public/common/content_switch_dependent_feature_overrides.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 ChromeFeatureListCreator::ChromeFeatureListCreator() = default;
 
@@ -89,7 +90,7 @@
   return std::move(browser_policy_connector_);
 }
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<installer::InitialPreferences>
 ChromeFeatureListCreator::TakeInitialPrefs() {
   return std::move(installer_initial_prefs_);
@@ -105,7 +106,7 @@
   auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>();
   RegisterLocalState(pref_registry.get());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // DBus must be initialized before constructing the policy connector.
   CHECK(chromeos::DBusThreadManager::IsInitialized());
   browser_policy_connector_ =
@@ -113,7 +114,7 @@
 #else
   browser_policy_connector_ =
       std::make_unique<policy::ChromeBrowserPolicyConnector>();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   local_state_ = chrome_prefs::CreateLocalState(
       local_state_file, browser_policy_connector_->GetPolicyService(),
@@ -138,7 +139,7 @@
 }
 
 void ChromeFeatureListCreator::ConvertFlagsToSwitches() {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Convert active flags into switches. This needs to be done before
   // ui::ResourceBundle::InitSharedInstanceWithLocale as some loaded resources
   // are affected by experiment flags (--touch-optimized-ui in particular). On
@@ -150,7 +151,7 @@
   about_flags::ConvertFlagsToSwitches(&flags_storage,
                                       base::CommandLine::ForCurrentProcess(),
                                       flags_ui::kAddSentinels);
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void ChromeFeatureListCreator::SetupFieldTrials() {
@@ -201,7 +202,7 @@
 void ChromeFeatureListCreator::SetupInitialPrefs() {
 // Android does first run in Java instead of native.
 // Chrome OS has its own out-of-box-experience code.
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   // On first run, we need to process the predictor preferences before the
   // browser's profile_manager object is created, but after ResourceBundle
   // is initialized.
@@ -236,5 +237,5 @@
     local_state_->SetInt64(variations::prefs::kVariationsSeedDate,
                            base::Time::Now().ToInternalValue());
   }
-#endif  // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif  // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 }
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h
index 6eb54101..a4b5477 100644
--- a/chrome/browser/metrics/chrome_feature_list_creator.h
+++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_browser_field_trials.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
@@ -57,7 +58,7 @@
   std::unique_ptr<policy::ChromeBrowserPolicyConnector>
   TakeChromeBrowserPolicyConnector();
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<installer::InitialPreferences> TakeInitialPrefs();
 #endif
 
@@ -102,7 +103,7 @@
 
   std::unique_ptr<ChromeBrowserFieldTrials> browser_field_trials_;
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<installer::InitialPreferences> installer_initial_prefs_;
 #endif
 
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.cc b/chrome/browser/metrics/chrome_metrics_service_accessor.cc
index f2f3065..1fd2d3d 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/pref_names.h"
@@ -12,7 +13,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #endif
 
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h
index d4eae00..6f5b524 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.h
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -11,6 +11,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_browser_field_trials_mobile.h"
 #include "chrome/browser/metrics/metrics_reporting_state.h"
 #include "chrome/common/metrics.mojom.h"
@@ -28,9 +29,9 @@
 class FlashDOMHandler;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class ChromeCameraAppUIDelegate;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace domain_reliability {
 class DomainReliabilityServiceFactory;
@@ -123,9 +124,9 @@
   friend class OptimizationGuideKeyedService;
   friend class WebUITabStripFieldTrial;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   friend class ChromeCameraAppUIDelegate;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Testing related friends.
   friend class first_run::FirstRunMasterPrefsVariationsSeedTest;
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 01e70823..b6e19e90 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -124,7 +124,7 @@
 #include <signal.h>
 #endif
 
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/service_process/service_process_control.h"
 #endif
 
@@ -139,11 +139,11 @@
 #include "chrome/browser/metrics/plugin_metrics_provider.h"
 #endif
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/metrics/lacros_metrics_provider.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/feature_list.h"
 #include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/browser/chromeos/printing/printer_metrics_provider.h"
@@ -156,7 +156,7 @@
 #include "chrome/browser/metrics/family_user_metrics_provider.h"
 #include "chrome/browser/signin/signin_status_metrics_provider_chromeos.h"
 #include "components/metrics/structured/structured_metrics_provider.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_WIN)
 #include <windows.h>
@@ -172,15 +172,15 @@
 #include "third_party/crashpad/crashpad/client/crashpad_info.h"
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/metrics/accessibility_metrics_provider.h"
 #include "chrome/browser/signin/chrome_signin_status_metrics_provider_delegate.h"
 #include "components/signin/core/browser/signin_status_metrics_provider.h"
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/metrics/upgrade_metrics_provider.h"
-#endif  //  !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif  // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
 #include "chrome/browser/metrics/power_metrics_provider_mac.h"
@@ -188,7 +188,7 @@
 
 namespace {
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
 const int kMaxHistogramStorageKiB = 100 << 10;  // 100 MiB
 #else
 const int kMaxHistogramStorageKiB = 500 << 10;  // 500 MiB
@@ -607,7 +607,7 @@
     RegisterUKMProviders();
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   metrics::structured::Recorder::GetInstance()->SetUiTaskRunner(
       base::SequencedTaskRunnerHandle::Get());
 #endif
@@ -694,12 +694,14 @@
       std::make_unique<AntiVirusMetricsProvider>());
 #endif  // defined(OS_WIN)
 
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<DesktopPlatformFeaturesMetricsProvider>());
-#endif  //  defined(OS_WIN) || defined(OS_MAC) || \
-        // (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#endif  // defined(OS_WIN) || defined(OS_MAC) || (defined(OS_LINUX) ||
+        // BUILDFLAG(IS_CHROMEOS_LACROS))
 
 #if BUILDFLAG(ENABLE_PLUGINS)
   plugin_metrics_provider_ = new PluginMetricsProvider(local_state);
@@ -707,12 +709,14 @@
       std::unique_ptr<metrics::MetricsProvider>(plugin_metrics_provider_));
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 
-#if BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<LacrosMetricsProvider>());
-#endif  // BUILDFLAG(IS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
-#if defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<ChromeOSMetricsProvider>(
           metrics::MetricsLogUploader::UMA));
@@ -754,16 +758,16 @@
     metrics_service_->RegisterMetricsProvider(
         std::make_unique<FamilyLinkUserMetricsProvider>());
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   metrics_service_->RegisterMetricsProvider(
       SigninStatusMetricsProvider::CreateInstance(
           std::make_unique<ChromeSigninStatusMetricsProviderDelegate>()));
   // ChromeOS uses ChromeOSMetricsProvider for accessibility metrics provider.
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<AccessibilityMetricsProvider>());
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<syncer::DeviceCountMetricsProvider>(base::BindRepeating(
@@ -779,10 +783,10 @@
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<CertificateReportingMetricsProvider>());
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<UpgradeMetricsProvider>());
-#endif  //! defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif  //! defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
   metrics_service_->RegisterMetricsProvider(
@@ -798,11 +802,11 @@
           content::CreateNetworkConnectionTrackerAsyncGetter(),
           std::make_unique<metrics::NetworkQualityEstimatorProviderImpl>()));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ukm_service_->RegisterMetricsProvider(
       std::make_unique<ChromeOSMetricsProvider>(
           metrics::MetricsLogUploader::UKM));
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   ukm_service_->RegisterMetricsProvider(
       std::make_unique<metrics::GPUMetricsProvider>());
@@ -853,7 +857,7 @@
 
   DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
 
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !BUILDFLAG(IS_CHROMEOS_ASH)
   num_async_histogram_fetches_in_progress_ = 3;
   // Run requests to service and content in parallel.
   if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
@@ -947,7 +951,7 @@
 }
 
 bool ChromeMetricsServiceClient::RegisterForProfileEvents(Profile* profile) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Ignore the signin and lock screen app profile for sync disables / history
   // deletion.
   if (chromeos::ProfileHelper::IsSigninProfile(profile) ||
@@ -972,8 +976,10 @@
         profile->GetPath());
   }
 #endif
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   // This creates the DesktopProfileSessionDurationsServices if it didn't exist
   // already.
   metrics::DesktopProfileSessionDurationsServiceFactory::GetForBrowserContext(
diff --git a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
index 0ef2dfd9..8713ebb 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -32,7 +33,7 @@
 #include "extensions/common/extension_builder.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #endif
@@ -55,20 +56,20 @@
             &ChromeMetricsServiceClientTest::LoadFakeClientInfoBackup,
             base::Unretained(this)));
     ASSERT_TRUE(profile_manager_.SetUp());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     scoped_feature_list_.InitAndEnableFeature(features::kUmaStorageDimensions);
     // ChromeOs Metrics Provider require g_login_state and power manager client
     // initialized before they can be instantiated.
     chromeos::PowerManagerClient::InitializeFake();
     chromeos::LoginState::Initialize();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   void TearDown() override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::LoginState::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     // ChromeMetricsServiceClient::Initialize() initializes
     // IdentifiabilityStudySettings as part of creating the
     // PrivacyBudgetUkmEntryFilter. Reset them after the test.
@@ -135,9 +136,9 @@
   // and ScreenInfoMetricsProvider.
   size_t expected_providers = 5;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   expected_providers++;  // ChromeOSMetricsProvider
-#endif                   // defined(OS_CHROMEOS)
+#endif                   // BUILDFLAG(IS_CHROMEOS_ASH)
 
   std::unique_ptr<ChromeMetricsServiceClient> chrome_metrics_service_client =
       ChromeMetricsServiceClient::Create(metrics_state_manager_.get());
@@ -179,34 +180,36 @@
   expected_providers++;
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // AmbientModeMetricsProvider, AssistantServiceMetricsProvider,
   // CrosHealthdMetricsProvider, ChromeOSMetricsProvider,
   // SigninStatusMetricsProviderChromeOS, PrinterMetricsProvider,
   // HashedLoggingMetricsProvider, FamilyUserMetricsProvider, and
   // FamilyLinkUserMetricsProvider.
   expected_providers += 9;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // ChromeSigninStatusMetricsProvider (for non ChromeOS).
   // AccessibilityMetricsProvider
   expected_providers += 2;
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   expected_providers++;  // UpgradeMetricsProvider
-#endif                   //! defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif                   //! defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_MAC)
   expected_providers++;  // PowerMetricsProvider
 #endif                   // defined(OS_MAC)
 
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_MAC) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   expected_providers++;  // DesktopPlatformFeaturesMetricsProvider
-#endif                   //  defined(OS_WIN) || defined(OS_MAC) || \
-                         // (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#endif  // defined(OS_WIN) || defined(OS_MAC) || (defined(OS_LINUX) ||
+        // BUILDFLAG(IS_CHROMEOS_LACROS))
 
   std::unique_ptr<ChromeMetricsServiceClient> chrome_metrics_service_client =
       ChromeMetricsServiceClient::Create(metrics_state_manager_.get());
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
index c2cfc10..9be5e5f98 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -15,6 +15,7 @@
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
@@ -50,9 +51,9 @@
 #include "components/crash/core/app/crashpad.h"
 #endif  // OS_WIN
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace metrics {
 
@@ -119,7 +120,7 @@
   return is_in_sample_group || !IsClientEligibleForSampling(local_state);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Callback to update the metrics reporting state when the Chrome OS metrics
 // reporting setting changes.
 void OnCrosMetricsReportingSettingChange() {
@@ -241,7 +242,7 @@
   return true;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void ChromeMetricsServicesManagerClient::OnCrosSettingsCreated() {
   reporting_setting_subscription_ =
       chromeos::StatsReportingController::Get()->AddObserver(
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.h b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
index cab3b70..74ba4f04 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.h
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
@@ -10,9 +10,10 @@
 #include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
+#include "build/chromeos_buildflags.h"
 #include "components/metrics_services_manager/metrics_services_manager_client.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
 #endif
 
@@ -61,7 +62,7 @@
   // eligible for sampling.
   static bool GetSamplingRatePerMille(int* rate);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnCrosSettingsCreated();
 #endif
 
@@ -103,7 +104,7 @@
   // Weak pointer to the local state prefs store.
   PrefService* const local_state_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   base::CallbackListSubscription reporting_setting_subscription_;
 #endif
 
diff --git a/chrome/browser/metrics/metrics_memory_details.cc b/chrome/browser/metrics/metrics_memory_details.cc
index df80a4f7..f1db7f4c 100644
--- a/chrome/browser/metrics/metrics_memory_details.cc
+++ b/chrome/browser/metrics/metrics_memory_details.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/site_isolation/site_details.h"
 #include "components/nacl/common/nacl_process_type.h"
 #include "content/public/browser/browser_thread.h"
@@ -157,7 +158,7 @@
         continue;
     }
   }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Chrome OS exposes system-wide graphics driver memory which has historically
   // been a source of leak/bloat.
   base::GraphicsMemoryInfoKB meminfo;
diff --git a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
index 919f204c..91b0b8e 100644
--- a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
+++ b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_browser_main.h"
 #include "chrome/browser/chrome_browser_main_extra_parts.h"
@@ -26,7 +27,7 @@
 #include "components/metrics/metrics_service_accessor.h"
 #include "content/public/test/browser_test.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/device_settings_cache.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/metrics/metrics_service_user_demographics_browsertest.cc b/chrome/browser/metrics/metrics_service_user_demographics_browsertest.cc
index 670a0615..24a2879 100644
--- a/chrome/browser/metrics/metrics_service_user_demographics_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_user_demographics_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
@@ -152,15 +153,15 @@
     histogram.ExpectTotalCount("UMA.UserDemographics.Status", /*count=*/0);
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Sign out the user to revoke all refresh tokens. This prevents any posted
   // tasks from successfully fetching an access token during the tear-down
   // phase and crashing on a DCHECK. See crbug/1102746 for more details.
   harness->SignOutPrimaryAccount();
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Cannot test for the enabled feature on Chrome OS because there are always
 // multiple profiles.
 static const auto kDemographicsTestParams = testing::Values(
diff --git a/chrome/browser/metrics/oom/out_of_memory_reporter.cc b/chrome/browser/metrics/oom/out_of_memory_reporter.cc
index d5c497c..126e4516 100644
--- a/chrome/browser/metrics/oom/out_of_memory_reporter.cc
+++ b/chrome/browser/metrics/oom/out_of_memory_reporter.cc
@@ -8,6 +8,7 @@
 
 #include "base/check.h"
 #include "base/time/default_tick_clock.h"
+#include "build/chromeos_buildflags.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -95,10 +96,10 @@
 // deterine OOM.
 #if !defined(OS_ANDROID)
   if (status == base::TERMINATION_STATUS_OOM
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       || status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM
 #endif
-      ) {
+  ) {
     OnForegroundOOMDetected(web_contents()->GetLastCommittedURL(),
                             *last_committed_source_id_);
   }
diff --git a/chrome/browser/metrics/oom/out_of_memory_reporter_unittest.cc b/chrome/browser/metrics/oom/out_of_memory_reporter_unittest.cc
index 16dbbeb..e3fe7c4 100644
--- a/chrome/browser/metrics/oom/out_of_memory_reporter_unittest.cc
+++ b/chrome/browser/metrics/oom/out_of_memory_reporter_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/task/post_task.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/ukm/content/source_url_recorder.h"
@@ -134,7 +135,7 @@
 #if defined(OS_ANDROID)
     process()->SimulateRenderProcessExit(base::TERMINATION_STATUS_OOM_PROTECTED,
                                          0);
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
     process()->SimulateRenderProcessExit(
         base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, 0);
 #else
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
index 58824b5b..116a383b 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -804,7 +804,7 @@
 
 // Test is flaky on chromeos and linux. https://crbug.com/938054.
 // Test is flaky on mac and win: https://crbug.com/948674.
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) ||        \
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) ||      \
     defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MAC) || \
     defined(OS_WIN)
 #define MAYBE_ForegroundAndBackgroundPages DISABLED_ForegroundAndBackgroundPages
diff --git a/chrome/browser/metrics/testing/metrics_reporting_pref_helper.cc b/chrome/browser/metrics/testing/metrics_reporting_pref_helper.cc
index dd3423b..3f1207ca 100644
--- a/chrome/browser/metrics/testing/metrics_reporting_pref_helper.cc
+++ b/chrome/browser/metrics/testing/metrics_reporting_pref_helper.cc
@@ -7,18 +7,19 @@
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/path_service.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "components/metrics/metrics_pref_names.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/device_settings_cache.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 namespace {
 
 void SetMetricsReportingEnabledChromeOS(
@@ -50,7 +51,7 @@
   if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
     return base::FilePath();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // ChromeOS checks a separate place for reporting enabled.
   SetMetricsReportingEnabledChromeOS(is_enabled, &local_state_dict);
 #endif
diff --git a/chrome/browser/metrics/testing/sync_metrics_test_utils.cc b/chrome/browser/metrics/testing/sync_metrics_test_utils.cc
index 09afc22..52aeb479 100644
--- a/chrome/browser/metrics/testing/sync_metrics_test_utils.cc
+++ b/chrome/browser/metrics/testing/sync_metrics_test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/metrics/testing/sync_metrics_test_utils.h"
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
@@ -25,7 +26,7 @@
               fake_server->AsWeakPtr()));
 
   std::string username;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // In browser tests, the profile may already by authenticated with stub
   // account |user_manager::kStubUserEmail|.
   CoreAccountInfo info =
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index e9a68f1e..9f682914 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -22,6 +22,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/metrics/thread_watcher_report_hang.h"
 #include "chrome/common/channel_info.h"
@@ -286,7 +287,7 @@
   base::TimeDelta response_time = now - ping_time_;
   response_time_histogram_->AddTime(response_time);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, we log when the response time is long on the UI thread as part
   // of an effort to debug extreme jank reported by some users. This log message
   // can be used to correlate the period of jank with other system logs.
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 7fa8145..8bbb883 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
@@ -323,9 +324,9 @@
   }
 
   void SetUpOnMainThread() override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     secondary_account_helper::InitNetwork();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     UkmBrowserTestBase::SetUpOnMainThread();
   }
 
@@ -680,16 +681,16 @@
     histogram.ExpectTotalCount("UKM.UserDemographics.Status", /*count=*/0);
   }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Sign out the user to revoke all refresh tokens. This prevents any posted
   // tasks from successfully fetching an access token during the tear-down
   // phase and crashing on a DCHECK. See crbug/1102746 for more details.
   harness->SignOutPrimaryAccount();
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   ClosePlatformBrowser(browser);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Cannot test for the enabled feature on Chrome OS because there are always
 // multiple profiles.
 static const auto kDemographicsTestParams = testing::Values(
@@ -987,7 +988,7 @@
 // Make sure that UKM is disabled when the profile signs out of Sync.
 // Keep in sync with testSingleSyncSignout in ios/chrome/browser/metrics/
 // ukm_egtest.mm.
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 IN_PROC_BROWSER_TEST_F(UkmBrowserTest, SingleSyncSignoutCheck) {
   ukm::UkmTestHelper ukm_test_helper(GetUkmService());
   MetricsConsentOverride metrics_consent(true);
@@ -1008,11 +1009,11 @@
   harness->service()->GetUserSettings()->SetSyncRequested(false);
   ClosePlatformBrowser(browser);
 }
-#endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 
 // ChromeOS doesn't have the concept of sign-out so this test doesn't make sense
 // there. Android doesn't have multiple profiles.
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 // Make sure that UKM is disabled when any profile signs out of Sync.
 IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MultiSyncSignoutCheck) {
   ukm::UkmTestHelper ukm_test_helper(GetUkmService());
@@ -1043,7 +1044,7 @@
   CloseBrowserSynchronously(browser2);
   CloseBrowserSynchronously(browser1);
 }
-#endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 
 // Make sure that if history/sync services weren't available when we tried to
 // attach listeners, UKM is not enabled.
@@ -1127,7 +1128,7 @@
 
 // On ChromeOS, the test profile starts with a primary account already set, so
 // this test doesn't apply.
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 IN_PROC_BROWSER_TEST_F(UkmBrowserTestWithSyncTransport,
                        NotEnabledForSecondaryAccountSync) {
   ukm::UkmTestHelper ukm_test_helper(GetUkmService());
@@ -1162,7 +1163,7 @@
 
   EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
 }
-#endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 
 #if !defined(OS_ANDROID)
 IN_PROC_BROWSER_TEST_P(UkmConsentParamBrowserTest, GroupPolicyConsentCheck) {
diff --git a/chrome/browser/metrics/variations/chrome_variations_service_client.cc b/chrome/browser/metrics/variations/chrome_variations_service_client.cc
index 3a7cd44..0d9bf83 100644
--- a/chrome/browser/metrics/variations/chrome_variations_service_client.cc
+++ b/chrome/browser/metrics/variations/chrome_variations_service_client.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_brand.h"
 #include "chrome/browser/net/system_network_context_manager.h"
@@ -13,17 +14,17 @@
 #include "components/version_info/version_info.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/upgrade_detector/upgrade_detector_impl.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #endif
 
 #if defined(OS_WIN) || defined(OS_MAC)
 #include "base/enterprise_util.h"
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/tpm/install_attributes.h"
 #endif
 
@@ -32,12 +33,12 @@
 // Gets the version number to use for variations seed simulation. Must be called
 // on a thread where IO is allowed.
 base::Version GetVersionForSimulation() {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   const base::Version installed_version =
       UpgradeDetectorImpl::GetCurrentlyInstalledVersion();
   if (installed_version.IsValid())
     return installed_version;
-#endif  // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif  // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // TODO(asvitkine): Get the version that will be used on restart instead of
   // the current version on Android, iOS and ChromeOS.
@@ -68,7 +69,7 @@
 
 bool ChromeVariationsServiceClient::OverridesRestrictParameter(
     std::string* parameter) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::CrosSettings::Get()->GetString(
       chromeos::kVariationsRestrictParameter, parameter);
   return true;
@@ -80,7 +81,7 @@
 bool ChromeVariationsServiceClient::IsEnterprise() {
 #if defined(OS_WIN) || defined(OS_MAC)
   return base::IsMachineExternallyManaged();
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return chromeos::InstallAttributes::Get()->IsEnterpriseManaged();
 #else
   return false;
diff --git a/chrome/browser/metrics/variations/force_field_trials_browsertest.cc b/chrome/browser/metrics/variations/force_field_trials_browsertest.cc
index f824bef..28a30c2c 100644
--- a/chrome/browser/metrics/variations/force_field_trials_browsertest.cc
+++ b/chrome/browser/metrics/variations/force_field_trials_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/system/sys_info.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -124,14 +125,14 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ForceFieldTrialsBrowserTest, ForceTrials) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO(asvitkine): This test fails on Linux Chrome OS bots. Since it passes
   // on proper Chrome OS bots, and Linux Chrome OS is not an end user
   // configuration, disable there for now. Would be good to understand the
   // problem at some point, though. crbug.com/947132
   if (!base::SysInfo::IsRunningOnChromeOS())
     return;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Create twenty one-time randomized field trials. Note: Loop is 1-indexed so
   // that we get trial names from "_TestTrial_1" to "_TestTrial_20". Since they
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index ffd6820..c5db4fb 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -10,7 +10,7 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "base/system/sys_info.h"
 #include "chrome/browser/download/download_prefs.h"
 #endif
@@ -29,13 +29,13 @@
   if (g_access_to_all_files_enabled)
     return true;
 
-#if !defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_LACROS) && \
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) && \
     !defined(OS_ANDROID)
   return true;
 #else
 
   std::vector<base::FilePath> allowlist;
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Use an allowlist to only allow access to files residing in the list of
   // directories below.
   static const base::FilePath::CharType* const kLocalAccessAllowList[] = {
@@ -111,7 +111,7 @@
     }
   }
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Allow access to DriveFS logs. These reside in
   // $PROFILE_PATH/GCache/v2/<opaque id>/Logs.
   base::FilePath path_within_gcache_v2;
@@ -123,11 +123,11 @@
       return true;
     }
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   DVLOG(1) << "File access denied - " << path.value().c_str();
   return false;
-#endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
 }
 
 }  // namespace
diff --git a/chrome/browser/net/chrome_network_delegate_browsertest.cc b/chrome/browser/net/chrome_network_delegate_browsertest.cc
index fc3bda6..bf8c42a 100644
--- a/chrome/browser/net/chrome_network_delegate_browsertest.cc
+++ b/chrome/browser/net/chrome_network_delegate_browsertest.cc
@@ -22,7 +22,7 @@
 #include "net/base/network_delegate.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
 class ChromeNetworkDelegateBrowserTest : public InProcessBrowserTest {
  protected:
@@ -90,4 +90,4 @@
   EXPECT_EQ(net::ERR_ACCESS_DENIED, observer.last_net_error_code());
 }
 
-#endif  // defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/net/chrome_network_delegate_unittest.cc b/chrome/browser/net/chrome_network_delegate_unittest.cc
index 5c93fda..31ea2647 100644
--- a/chrome/browser/net/chrome_network_delegate_unittest.cc
+++ b/chrome/browser/net/chrome_network_delegate_unittest.cc
@@ -11,7 +11,7 @@
 #include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "base/system/sys_info.h"
 #include "base/test/scoped_running_on_chromeos.h"
 #include "base/time/time.h"
@@ -35,7 +35,8 @@
 }  // namespace
 
 TEST(ChromeNetworkDelegateStaticTest, IsAccessAllowed) {
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) || \
+    defined(OS_ANDROID)
   // Chrome OS and Android don't have access to random files.
   EXPECT_FALSE(IsAccessAllowed("/", ""));
   EXPECT_FALSE(IsAccessAllowed("/foo.txt", ""));
@@ -47,7 +48,7 @@
   EXPECT_TRUE(IsAccessAllowed("/foo.txt", ""));
 #endif
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   base::FilePath temp_dir;
   ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
   // Chrome OS allows the following directories.
diff --git a/chrome/browser/net/errorpage_browsertest.cc b/chrome/browser/net/errorpage_browsertest.cc
index 776ca58..e5312e2f 100644
--- a/chrome/browser/net/errorpage_browsertest.cc
+++ b/chrome/browser/net/errorpage_browsertest.cc
@@ -79,7 +79,7 @@
 #include "services/network/public/cpp/features.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -88,6 +88,7 @@
 #else
 #include "chrome/browser/policy/profile_policy_connector_builder.h"
 #endif
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 
 using content::BrowserThread;
@@ -495,7 +496,9 @@
 // This test fails regularly on win_rel trybots. See crbug.com/121540
 //
 // This fails on linux_aura bringup: http://crbug.com/163931
-#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
+#if defined(OS_WIN) ||                                       \
+    ((defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     defined(USE_AURA))
 #define MAYBE_IFrameDNSError_GoBackAndForward DISABLED_IFrameDNSError_GoBackAndForward
 #else
 #define MAYBE_IFrameDNSError_GoBackAndForward IFrameDNSError_GoBackAndForward
@@ -636,7 +639,7 @@
   // Verify that the expected error page is being displayed.
   ExpectDisplayingErrorPage(incognito_browser, net::ERR_NAME_NOT_RESOLVED);
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Can't currently show the diagnostics in incognito on any platform but
   // ChromeOS.
   EXPECT_FALSE(WebContentsCanShowDiagnosticsTool(
@@ -824,7 +827,7 @@
 
  protected:
   void SetUpInProcessBrowserTestFixture() override {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (enroll_) {
       // Set up fake install attributes.
       test_install_attributes_ =
@@ -841,7 +844,7 @@
         .WillRepeatedly(testing::Return(true));
 
     policy::PolicyMap policy_map;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (enroll_)
       SetEnterpriseUsersDefaults(&policy_map);
 #endif
@@ -853,7 +856,7 @@
     }
     policy_provider_.UpdateChromePolicy(policy_map);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
         &policy_provider_);
 #else
@@ -864,7 +867,7 @@
   }
 
   std::string NavigateToPageAndReadText() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // Check enterprise enrollment
     policy::BrowserPolicyConnectorChromeOS* connector =
         g_browser_process->platform_part()
@@ -896,7 +899,7 @@
   // The value of AllowDinosaurEasterEgg policy we want to set
   bool value_of_allow_dinosaur_easter_egg_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Whether to enroll this CrOS device
   bool enroll_ = true;
 
@@ -927,7 +930,7 @@
   }
 };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class ErrorPageOfflineTestUnEnrolledChromeOS : public ErrorPageOfflineTest {
  protected:
   void SetUpInProcessBrowserTestFixture() override {
@@ -952,7 +955,7 @@
   EXPECT_EQ(disabled_text, result);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTest, CheckEasterEggIsDisabled) {
   std::string result = NavigateToPageAndReadText();
   std::string disabled_text =
@@ -966,7 +969,7 @@
 }
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(ErrorPageOfflineTestUnEnrolledChromeOS,
                        CheckEasterEggIsAllowed) {
   std::string result = NavigateToPageAndReadText();
diff --git a/chrome/browser/net/load_timing_browsertest.cc b/chrome/browser/net/load_timing_browsertest.cc
index 2f696ba..e2e19372 100644
--- a/chrome/browser/net/load_timing_browsertest.cc
+++ b/chrome/browser/net/load_timing_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/profile_network_context_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -133,7 +134,7 @@
 }
 
 // TODO(crbug.com/1128033): Flaky on ChromeOS.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_HTTPS DISABLED_HTTPS
 #else
 #define MAYBE_HTTPS HTTPS
diff --git a/chrome/browser/net/network_connection_tracker_browsertest.cc b/chrome/browser/net/network_connection_tracker_browsertest.cc
index 00bc916..2529b3f2 100644
--- a/chrome/browser/net/network_connection_tracker_browsertest.cc
+++ b/chrome/browser/net/network_connection_tracker_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/sequence_checker.h"
 #include "base/test/bind.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -115,7 +116,7 @@
   // NetworkService on ChromeOS doesn't yet have a NetworkChangeManager
   // implementation. OSX uses a separate binary for service processes and
   // browser test fixture doesn't have NetworkServiceTest mojo code.
-#if !defined(OS_CHROMEOS) && !defined(OS_MAC)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_MAC)
   network::NetworkConnectionTracker* tracker =
       content::GetNetworkConnectionTracker();
   EXPECT_NE(nullptr, tracker);
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index 362a180..f427933 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -266,7 +267,7 @@
       incognito_ = CreateIncognitoBrowser();
     SimulateNetworkServiceCrashIfNecessary();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // On ChromeOS the connection type comes from a fake Shill service, which
     // is configured with a fake ethernet connection asynchronously. Wait for
     // the connection type to be available to avoid getting notified of the
diff --git a/chrome/browser/net/nss_context.h b/chrome/browser/net/nss_context.h
index 2b3b6c6..9a389e7 100644
--- a/chrome/browser/net/nss_context.h
+++ b/chrome/browser/net/nss_context.h
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "crypto/scoped_nss_types.h"
 
 class Profile;
@@ -33,7 +34,7 @@
     base::OnceCallback<void(net::NSSCertDatabase*)> callback)
     WARN_UNUSED_RESULT;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Enables the system key slot in the NSSCertDatabase for the user associated
 // with |context|.
 // Must be called only on the IO thread.
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index eba2871..0b849227 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_split.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -61,7 +62,7 @@
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "third_party/blink/public/common/features.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider.h"
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
@@ -119,7 +120,7 @@
   return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 network::mojom::AdditionalCertificatesPtr GetAdditionalCertificates(
     const policy::PolicyCertService* policy_cert_service,
     const base::FilePath& storage_partition_path) {
@@ -297,7 +298,7 @@
   }
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void ProfileNetworkContextService::UpdateAdditionalCertificates() {
   const policy::PolicyCertService* policy_cert_service =
       policy::PolicyCertServiceFactory::GetForProfile(profile_);
@@ -532,7 +533,7 @@
   if (!client_cert_store_factory_.is_null())
     return client_cert_store_factory_.Run();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool use_system_key_slot = false;
   // Enable client certificates for the Chrome OS sign-in frame, if this feature
   // is not disabled by a flag.
@@ -802,7 +803,7 @@
     drp_settings->AddCustomProxyConfigClient(std::move(config_client));
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool profile_supports_policy_certs = false;
   if (chromeos::ProfileHelper::IsSigninProfile(profile_))
     profile_supports_policy_certs = true;
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h
index bc4fda4..9526231a 100644
--- a/chrome/browser/net/profile_network_context_service.h
+++ b/chrome/browser/net/profile_network_context_service.h
@@ -17,6 +17,7 @@
 #include "base/scoped_observer.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/net/proxy_config_monitor.h"
 #include "components/content_settings/core/browser/content_settings_observer.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
@@ -69,7 +70,7 @@
       network::mojom::CertVerifierCreationParams*
           cert_verifier_creation_params);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void UpdateAdditionalCertificates();
 #endif
 
diff --git a/chrome/browser/net/profile_network_context_service_browsertest.cc b/chrome/browser/net/profile_network_context_service_browsertest.cc
index a29908b..4b55e9e69 100644
--- a/chrome/browser/net/profile_network_context_service_browsertest.cc
+++ b/chrome/browser/net/profile_network_context_service_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/threading/platform_thread.h"  // For |Sleep()|.
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/profile_network_context_service_factory.h"
@@ -322,7 +323,7 @@
                   policy_value));
 // ChromeOS guest sessions don't have the capability to
 // do ambient authentications.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     EXPECT_EQ(
         AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
             CreateGuestBrowser()->profile()),
diff --git a/chrome/browser/net/profile_network_context_service_factory.cc b/chrome/browser/net/profile_network_context_service_factory.cc
index 79ae2e1..a3a14da 100644
--- a/chrome/browser/net/profile_network_context_service_factory.cc
+++ b/chrome/browser/net/profile_network_context_service_factory.cc
@@ -5,11 +5,12 @@
 #include "chrome/browser/net/profile_network_context_service_factory.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
 #endif
 
@@ -29,7 +30,7 @@
     : BrowserContextKeyedServiceFactory(
           "ProfileNetworkContextService",
           BrowserContextDependencyManager::GetInstance()) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   DependsOn(chromeos::CertificateProviderServiceFactory::GetInstance());
 #endif
 }
diff --git a/chrome/browser/net/proxy_browsertest.cc b/chrome/browser/net/proxy_browsertest.cc
index 07be151..27a35c8 100644
--- a/chrome/browser/net/proxy_browsertest.cc
+++ b/chrome/browser/net/proxy_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/net/proxy_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
@@ -42,9 +43,9 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/net/dhcp_wpad_url_client.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -175,7 +176,7 @@
   VerifyProxyScript(browser());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests the use of a PAC script set via Web Proxy Autodiscovery Protocol.
 // TODO(crbug.com/991867): Add a test case for when DhcpWpadUrlClient
 // returns an empty PAC URL.
@@ -208,7 +209,7 @@
 IN_PROC_BROWSER_TEST_F(WPADHttpProxyScriptBrowserTest, Verify) {
   VerifyProxyScript(browser());
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Tests the use of a PAC script that rejects requests to http://www.google.com/
 // when myIpAddress() and myIpAddressEx() appear to be working.
diff --git a/chrome/browser/net/proxy_config_monitor.cc b/chrome/browser/net/proxy_config_monitor.cc
index dc1ffcf..08a7a02 100644
--- a/chrome/browser/net/proxy_config_monitor.cc
+++ b/chrome/browser/net/proxy_config_monitor.cc
@@ -8,6 +8,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/proxy_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -16,9 +17,9 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
@@ -36,13 +37,13 @@
 
 // If this is the ChromeOS sign-in profile, just create the tracker from global
 // state.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
     pref_proxy_config_tracker_ =
         ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
             g_browser_process->local_state());
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   if (!pref_proxy_config_tracker_) {
     pref_proxy_config_tracker_ =
diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc
index 5284a68..9f6edc5 100644
--- a/chrome/browser/net/proxy_service_factory.cc
+++ b/chrome/browser/net/proxy_service_factory.cc
@@ -9,15 +9,16 @@
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_config_service.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/network/proxy/proxy_config_service_impl.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 using content::BrowserThread;
 
@@ -32,7 +33,7 @@
 
   std::unique_ptr<net::ProxyConfigService> base_service;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, base service is NULL; chromeos::ProxyConfigServiceImpl
   // determines the effective proxy config to take effect in the network layer,
   // be it from prefs or system (which is network shill on chromeos).
@@ -44,7 +45,7 @@
   base_service =
       net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService(
           base::ThreadTaskRunnerHandle::Get());
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   return tracker->CreateTrackingProxyConfigService(std::move(base_service));
 }
@@ -54,23 +55,23 @@
 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
     PrefService* profile_prefs,
     PrefService* local_state_prefs) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return std::make_unique<chromeos::ProxyConfigServiceImpl>(
       profile_prefs, local_state_prefs, nullptr);
 #else
   return std::make_unique<PrefProxyConfigTrackerImpl>(profile_prefs, nullptr);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // static
 std::unique_ptr<PrefProxyConfigTracker>
 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
     PrefService* local_state_prefs) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return std::make_unique<chromeos::ProxyConfigServiceImpl>(
       nullptr, local_state_prefs, nullptr);
 #else
   return std::make_unique<PrefProxyConfigTrackerImpl>(local_state_prefs,
                                                       nullptr);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
diff --git a/chrome/browser/net/stub_resolver_config_reader.cc b/chrome/browser/net/stub_resolver_config_reader.cc
index 2bddf0be..677f6c5 100644
--- a/chrome/browser/net/stub_resolver_config_reader.cc
+++ b/chrome/browser/net/stub_resolver_config_reader.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_piece.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/secure_dns_config.h"
 #include "chrome/browser/net/secure_dns_util.h"
@@ -226,7 +227,7 @@
   if (base::IsMachineExternallyManaged())
     return true;
 #endif
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   if (g_browser_process->browser_policy_connector()->HasMachineLevelPolicies())
     return true;
 #endif
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index c45a5a7..bd19efb 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -19,6 +19,7 @@
 #include "base/task/post_task.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/component_updater/crl_set_component_installer.h"
@@ -71,17 +72,19 @@
 #include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chromeos/net/dhcp_wpad_url_client.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/grit/chromium_strings.h"
 #include "ui/base/l10n/l10n_util.h"
-#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "extensions/common/constants.h"
@@ -117,7 +120,7 @@
       base::SplitString(local_state->GetString(prefs::kAuthSchemes), ",",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   auth_static_params->gssapi_library_name =
       local_state->GetString(prefs::kGSSAPILibraryName);
 #endif
@@ -157,7 +160,7 @@
       local_state->GetString(prefs::kAuthAndroidNegotiateAccountType);
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO: Use KerberosCredentialsManager to determine whether Kerberos is
   // enabled instead of relying directly on the preference.
   policy::BrowserPolicyConnectorChromeOS* connector =
@@ -374,11 +377,11 @@
                              auth_pref_callback);
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO: Use KerberosCredentialsManager::Observer to be notified of when the
   // enabled state changes instead of relying directly on the preference.
   pref_change_registrar_.Add(prefs::kKerberosEnabled, auth_pref_callback);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   local_state_->SetDefaultPrefValue(
       prefs::kEnableReferrers,
@@ -400,9 +403,10 @@
   // Static auth params
   registry->RegisterStringPref(prefs::kAuthSchemes,
                                "basic,digest,ntlm,negotiate");
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string());
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) &&
+        // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Dynamic auth params.
   registry->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, false);
@@ -506,7 +510,9 @@
   // NetworkContext is created, but before anything has the chance to use it.
   stub_resolver_config_reader_.UpdateNetworkService(true /* record_metrics */);
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
 
@@ -599,10 +605,10 @@
     } else {
       network_context_params->proxy_resolver_factory =
           ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       network_context_params->dhcp_wpad_url_client =
           chromeos::DhcpWpadUrlClient::CreateWithSelfOwnedReceiver();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     }
   }
 
diff --git a/chrome/browser/net/system_network_context_manager_browsertest.cc b/chrome/browser/net/system_network_context_manager_browsertest.cc
index 25a9096e..41b196a1 100644
--- a/chrome/browser/net/system_network_context_manager_browsertest.cc
+++ b/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/secure_dns_config.h"
 #include "chrome/browser/net/stub_resolver_config_reader.h"
@@ -213,7 +214,7 @@
       SystemNetworkContextManager::GetHttpAuthStaticParamsForTesting();
   EXPECT_THAT(static_params->supported_schemes, testing::ElementsAre("basic"));
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   const char dev_null[] = "/dev/null";
   local_state->SetString(prefs::kGSSAPILibraryName, dev_null);
   static_params =
@@ -299,7 +300,7 @@
   EXPECT_TRUE(dynamic_params->delegate_by_kdc_policy);
 #endif  // defined(OS_LINUX) || defined(OS_MAC) || defined(OS_CHROMEOS)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // The kerberos.enabled pref is false and the device is not Active Directory
   // managed by default.
   EXPECT_FALSE(dynamic_params->allow_gssapi_library_load);
@@ -307,7 +308,7 @@
   dynamic_params =
       SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
   EXPECT_TRUE(dynamic_params->allow_gssapi_library_load);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 class SystemNetworkContextManagerStubResolverBrowsertest
diff --git a/chrome/browser/password_manager/android/password_infobar_utils.cc b/chrome/browser/password_manager/android/password_infobar_utils.cc
new file mode 100644
index 0000000..c729f8e
--- /dev/null
+++ b/chrome/browser/password_manager/android/password_infobar_utils.cc
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/password_manager/android/password_infobar_utils.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+namespace password_manager {
+base::Optional<AccountInfo> GetAccountInfoForPasswordInfobars(Profile* profile,
+                                                              bool is_syncing) {
+  DCHECK(profile);
+  if (!base::FeatureList::IsEnabled(
+          autofill::features::
+              kAutofillEnablePasswordInfoBarAccountIndicationFooter) ||
+      !is_syncing ||
+      !base::FeatureList::IsEnabled(
+          autofill::features::
+              kAutofillEnableInfoBarAccountIndicationFooterForSyncUsers)) {
+    return base::nullopt;
+  }
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
+  CoreAccountId account_id =
+      identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync);
+  base::Optional<AccountInfo> account_info =
+      identity_manager
+          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+              account_id);
+  bool is_single_account_user =
+      identity_manager->GetAccountsWithRefreshTokens().size() == 1;
+
+  bool should_show_account_footer =
+      (!is_single_account_user ||
+       base::FeatureList::IsEnabled(
+           autofill::features::
+               kAutofillEnableInfoBarAccountIndicationFooterForSingleAccountUsers)) &&
+      account_info.has_value();
+
+  return should_show_account_footer ? account_info : base::nullopt;
+}
+
+}  // namespace password_manager
diff --git a/chrome/browser/password_manager/android/password_infobar_utils.h b/chrome/browser/password_manager/android/password_infobar_utils.h
new file mode 100644
index 0000000..eedc98a31
--- /dev/null
+++ b/chrome/browser/password_manager/android/password_infobar_utils.h
@@ -0,0 +1,19 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_INFOBAR_UTILS_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_INFOBAR_UTILS_H_
+
+#include "components/signin/public/identity_manager/account_info.h"
+
+class Profile;
+
+namespace password_manager {
+
+base::Optional<AccountInfo> GetAccountInfoForPasswordInfobars(Profile* profile,
+                                                              bool is_syncing);
+
+}  // namespace password_manager
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_INFOBAR_UTILS_H_
diff --git a/chrome/browser/password_manager/android/save_password_infobar_delegate_android.cc b/chrome/browser/password_manager/android/save_password_infobar_delegate_android.cc
index 44e4927..1d9b890 100644
--- a/chrome/browser/password_manager/android/save_password_infobar_delegate_android.cc
+++ b/chrome/browser/password_manager/android/save_password_infobar_delegate_android.cc
@@ -11,21 +11,17 @@
 #include "base/scoped_observer.h"
 #include "base/values.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/password_manager/android/password_infobar_utils.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/android/infobars/save_password_infobar.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/autofill/core/common/autofill_features.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
-#include "components/signin/public/identity_manager/account_info.h"
-#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/sync/driver/sync_service.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -39,38 +35,18 @@
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile);
-  signin::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile);
-  CoreAccountId account_id =
-      identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync);
-  base::Optional<AccountInfo> account_info =
-      identity_manager
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id);
-  bool is_single_account_user =
-      identity_manager->GetAccountsWithRefreshTokens().size() == 1;
-
   // is_smartlock_branding_enabled indicates whether the user is syncing
   // passwords to their Google Account.
   bool is_smartlock_branding_enabled =
       password_bubble_experiment::IsSmartLockUser(sync_service);
-  bool should_show_account_footer =
-      (is_smartlock_branding_enabled &&
-       base::FeatureList::IsEnabled(
-           autofill::features::
-               kAutofillEnableInfoBarAccountIndicationFooterForSyncUsers)) &&
-      (!is_single_account_user ||
-       base::FeatureList::IsEnabled(
-           autofill::features::
-               kAutofillEnableInfoBarAccountIndicationFooterForSingleAccountUsers)) &&
-      account_info.has_value();
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(web_contents);
   infobar_service->AddInfoBar(std::make_unique<SavePasswordInfoBar>(
       base::WrapUnique(
           new SavePasswordInfoBarDelegate(web_contents, std::move(form_to_save),
                                           is_smartlock_branding_enabled)),
-      should_show_account_footer ? account_info : base::nullopt));
+      password_manager::GetAccountInfoForPasswordInfobars(
+          profile, /*is_syncing=*/is_smartlock_branding_enabled)));
 }
 
 SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() {
diff --git a/chrome/browser/password_manager/android/update_password_infobar_delegate_android.cc b/chrome/browser/password_manager/android/update_password_infobar_delegate_android.cc
index 9372f9e..39aa4b3 100644
--- a/chrome/browser/password_manager/android/update_password_infobar_delegate_android.cc
+++ b/chrome/browser/password_manager/android/update_password_infobar_delegate_android.cc
@@ -7,6 +7,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/password_manager/android/password_infobar_utils.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -27,6 +28,10 @@
 void UpdatePasswordInfoBarDelegate::Create(
     content::WebContents* web_contents,
     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  // is_smartlock_branding_enabled indicates whether the user is syncing
+  // passwords to their Google Account.
   const bool is_smartlock_branding_enabled =
       password_bubble_experiment::IsSmartLockUser(
           ProfileSyncServiceFactory::GetForProfile(
@@ -35,7 +40,9 @@
       ->AddInfoBar(std::make_unique<UpdatePasswordInfoBar>(
           base::WrapUnique(new UpdatePasswordInfoBarDelegate(
               web_contents, std::move(form_to_save),
-              is_smartlock_branding_enabled))));
+              is_smartlock_branding_enabled)),
+          password_manager::GetAccountInfoForPasswordInfobars(
+              profile, /*is_syncing=*/is_smartlock_branding_enabled)));
 }
 
 UpdatePasswordInfoBarDelegate::~UpdatePasswordInfoBarDelegate() {
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index b0ff255..2575eb8 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -2284,7 +2284,14 @@
   SendCopyCommandAndCheckCopyPasteClipboard("HEL");
 }
 
-IN_PROC_BROWSER_TEST_P(PDFExtensionClipboardTest, CombinedShiftArrowPresses) {
+// Flaky on ChromeOS (https://crbug.com/1121446)
+#if defined(OS_LINUX)
+#define MAYBE_CombinedShiftArrowPresses DISABLED_CombinedShiftArrowPresses
+#else
+#define MAYBE_CombinedShiftArrowPresses CombinedShiftArrowPresses
+#endif
+IN_PROC_BROWSER_TEST_P(PDFExtensionClipboardTest,
+                       MAYBE_CombinedShiftArrowPresses) {
   LoadTestComboBoxPdfGetGuestContents();
 
   // Give the editable combo box focus.
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index f84ee3a..1112fe5 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1124,6 +1124,9 @@
   { key::kSystemFeaturesDisableMode,
     policy::policy_prefs::kSystemFeaturesDisableMode,
     base::Value::Type::STRING },
+    { key::kIntegratedWebAuthenticationAllowed,
+    prefs::kIntegratedWebAuthenticationAllowed,
+    base::Value::Type::BOOLEAN },
 #else // BUILDFLAG(IS_CHROMEOS_ASH)
   { key::kMetricsReportingEnabled,
     metrics::prefs::kMetricsReportingEnabled,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 0bb292c..d0bfa08 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1209,7 +1209,13 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenLinkInProfile) {
+// Test is flaky on Win and Mac dbg: crbug.com/1121731
+#if defined(OS_WIN) || (defined(OS_MAC) && !defined(NDEBUG))
+#define MAYBE_OpenLinkInProfile DISABLED_OpenLinkInProfile
+#else
+#define MAYBE_OpenLinkInProfile OpenLinkInProfile
+#endif
+IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, MAYBE_OpenLinkInProfile) {
   // Create |num_profiles| extra profiles for testing.
   const int num_profiles = 8;
   // The following are the profile numbers that are omitted and need signin.
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 495f3e90..122ab03 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/browser/buildflags.gni")
 import("//chrome/common/features.gni")
 import("//chrome/test/base/js2gtest.gni")
@@ -65,7 +66,7 @@
     if (is_linux || is_chromeos) {
       deps += [ "webui_js_error:closure_compile" ]
     }
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       deps += [
         "chromeos:closure_compile",
         "nearby_share:closure_compile",
@@ -94,7 +95,7 @@
         "webapks:closure_compile",
       ]
     }
-    if (is_win || is_mac || is_linux) {
+    if (is_win || is_mac || is_linux || is_chromeos_lacros) {
       deps += [ "browser_switch:closure_compile" ]
     }
 
@@ -203,7 +204,7 @@
   }
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   grit("multidevice_internals_resources") {
     source =
         "chromeos/multidevice_internals/multidevice_internals_resources.grd"
diff --git a/chrome/browser/resources/chromeos/accessibility/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/BUILD.gn
index 3216176b..dfddba7 100644
--- a/chrome/browser/resources/chromeos/accessibility/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/BUILD.gn
@@ -2,13 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//chrome/common/features.gni")
 import("//chrome/test/base/js2gtest.gni")
 import("//chromecast/chromecast.gni")
 import("strings/accessibility_strings.gni")
 
-assert(is_chromeos || is_chromecast)
+assert(is_chromeos_ash || is_chromecast)
 
 accessibility_out_dir = "$root_out_dir/resources/chromeos/accessibility/"
 
@@ -20,7 +21,7 @@
     "chromevox:build",
     "common:build",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       ":accessibility_common_guest_manifest",
       ":accessibility_common_manifest",
@@ -120,7 +121,7 @@
 
 group("browser_tests") {
   testonly = true
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps = [
       "accessibility_common:browser_tests",
       "chromevox:browser_tests",
@@ -133,7 +134,7 @@
 
 group("unit_tests_js") {
   testonly = true
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps = [
       ":misc_unit_tests_js",
       "chromevox:chromevox_unit_js_tests",
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
index effd165..e21da6b 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import(
     "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni")
@@ -9,7 +10,7 @@
 import("//testing/test.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 
 accessibility_common_dir =
     "$root_out_dir/resources/chromeos/accessibility/accessibility_common"
diff --git a/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
index 87c9f49..963487ff 100644
--- a/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chromecast/chromecast.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
-assert(is_chromeos || is_chromecast)
+assert(is_chromeos_ash || is_chromecast)
 
 copy("braille_ime_manifest") {
   sources = [ "manifest.json" ]
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
index 2d50d6a..d5de3fa 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import(
     "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni")
@@ -330,7 +331,7 @@
   }
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   source_set("browser_tests") {
     testonly = true
     assert(enable_extensions)
diff --git a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
index 0eddc03..a824df5 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import(
     "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni")
@@ -11,7 +12,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
 
-assert(is_chromeos || is_chromecast)
+assert(is_chromeos_ash || is_chromecast)
 
 accessibility_common_out_dir =
     "$root_out_dir/resources/chromeos/accessibility/common"
@@ -159,7 +160,7 @@
     "testing/e2e_test_base.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     # The test base classes generate C++ code with these deps.
     deps = [
       "//ash",
diff --git a/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni b/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni
index 1a669e0..a7481653 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni
+++ b/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni
@@ -1,10 +1,11 @@
 # Copyright 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/python.gni")
 import("//chromecast/chromecast.gni")
 
-assert(is_chromeos || is_chromecast)
+assert(is_chromeos_ash || is_chromecast)
 
 closure_library_dir =
     "//third_party/chromevox/third_party/closure-library/closure/goog"
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
index 3f2238e..c58e9cdc 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import(
     "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni")
@@ -10,7 +11,7 @@
 import("//testing/test.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 
 select_to_speak_out_dir =
     "$root_out_dir/resources/chromeos/accessibility/select_to_speak"
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
index 5a372b5..4255b60 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import(
     "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni")
@@ -10,7 +11,7 @@
 import("//testing/test.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
-assert(is_chromeos)
+assert(is_chromeos_ash)
 
 switch_access_dir =
     "$root_out_dir/resources/chromeos/accessibility/switch_access"
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index cfed148..d8f5235 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/common/features.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
@@ -74,7 +75,7 @@
     "shortcut_util.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [ "kiosk_browser_proxy.js" ]
   }
 }
@@ -116,7 +117,7 @@
     "toolbar.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [ "kiosk_dialog.js" ]
   }
 }
@@ -163,7 +164,7 @@
     "toolbar.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     js_files += [ "kiosk_dialog.js" ]
   }
 }
@@ -218,7 +219,7 @@
     ":toggle_row",
     ":toolbar",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ ":kiosk_dialog" ]
   }
 }
@@ -356,7 +357,7 @@
   deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   js_library("kiosk_dialog") {
     deps = [
       ":item_behavior",
diff --git a/chrome/browser/resources/gaia_auth_host/BUILD.gn b/chrome/browser/resources/gaia_auth_host/BUILD.gn
index 944cf97..24f0c63 100644
--- a/chrome/browser/resources/gaia_auth_host/BUILD.gn
+++ b/chrome/browser/resources/gaia_auth_host/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/test/base/js2gtest.gni")
 import("//chrome/test/include_js_tests.gni")
 import("//third_party/closure_compiler/compile_js.gni")
@@ -10,7 +11,7 @@
 # Since js2gtest()s don't compile in some scenarios when include_js_tests is
 # false, and since this file may be loaded even when it's false, we need to make
 # sure the js2gtest() target only exists in this file when it works.
-if (is_chromeos && include_js_tests) {
+if (is_chromeos_ash && include_js_tests) {
   js2gtest("login_unitjs_tests") {
     # These could be unit tests, except they need a browser context in order
     # to construct a DOMParser object - so they are webui tests.
diff --git a/chrome/browser/resources/nearby_share/shared/BUILD.gn b/chrome/browser/resources/nearby_share/shared/BUILD.gn
index 27dce877..992cfdd5 100644
--- a/chrome/browser/resources/nearby_share/shared/BUILD.gn
+++ b/chrome/browser/resources/nearby_share/shared/BUILD.gn
@@ -104,7 +104,9 @@
     "//ui/webui/resources/cr_elements/cr_radio_button:cr_card_radio_button",
     "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group",
     "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:i18n_behavior",
+    "//ui/webui/resources/js:load_time_data",
   ]
 }
 
@@ -196,7 +198,9 @@
     "//ui/webui/resources/cr_elements/cr_radio_button:cr_card_radio_button.m",
     "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m",
     "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:cr.m",
     "//ui/webui/resources/js:i18n_behavior.m",
+    "//ui/webui/resources/js:load_time_data.m",
   ]
   extra_deps = [ ":nearby_contact_visibility_module" ]
 }
diff --git a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.html b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.html
index 661ca90..d270e63 100644
--- a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.html
+++ b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.html
@@ -6,7 +6,9 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="nearby_contact_manager.html">
@@ -25,7 +27,11 @@
       }
 
       .grey-icon {
-        color: var(--google-grey-refresh-700);
+        fill: var(--google-grey-refresh-700);
+      }
+
+      .light-grey-icon {
+        fill: var(--google-grey-refresh-500);
       }
 
       #main {
@@ -175,6 +181,12 @@
         font-size: 1.2rem;
       }
 
+      #unreachableMessage {
+        color: var(--google-grey-refresh-500);
+        font-size: 11px;
+        line-height: 16px;
+      }
+
       .contact-item {
         display: flex;
         height: 40px;
@@ -220,29 +232,32 @@
       <cr-radio-group id="visibilityRadioGroup"
           disabled="[[disableRadioGroup_(contactsState)]]"
           selected="{{selectedVisibility}}">
-        <cr-card-radio-button id="allContacts" class="flex" name="all">
+        <cr-card-radio-button id="allContacts" class="flex" name="all"
+            aria-labelledby="allContactsLabel">
           <div class="card-contents">
             <iron-icon icon="nearby20:contact-all" class="card-icon">
             </iron-icon>
-            <div class="card-label">
+            <div id="allContactsLabel" class="card-label" aria-hidden="true">
               $i18n{nearbyShareContactVisibilityAll}
             </div>
           </div>
         </cr-card-radio-button>
-        <cr-card-radio-button id="someContacts" class="flex" name="some">
+        <cr-card-radio-button id="someContacts" class="flex" name="some"
+            aria-labelledby="someContactsLabel">
           <div class="card-contents">
             <iron-icon icon="nearby20:contact-group" class="card-icon">
             </iron-icon>
-            <div class="card-label">
+            <div id="someContactsLabel" class="card-label" aria-hidden="true">
               $i18n{nearbyShareContactVisibilitySome}
             </div>
           </div>
         </cr-card-radio-button>
-        <cr-card-radio-button id="noContacts" class="flex" name="none">
+        <cr-card-radio-button id="noContacts" class="flex" name="none"
+            aria-labelledby="noContactsLabel">
           <div class="card-contents">
             <iron-icon icon="nearby20:visibility-off" class="card-icon">
             </iron-icon>
-            <div class="card-label">
+            <div id="noContactsLabel" class="card-label" aria-hidden="true">
               $i18n{nearbyShareContactVisibilityNone}
             </div>
           </div>
@@ -370,6 +385,18 @@
               if="[[showContactList_(selectedVisibility,
                   contactsState)]]">
             <div id="contactList">
+              <template is="dom-if"
+                  if="[[showUnreachableContactsMessage_(
+                      numUnreachable_)]]">
+                <div class="explanation-section">
+                  <iron-icon icon="nearby20:info"
+                      class="padded-icon light-grey-icon">
+                  </iron-icon>
+                  <div id="unreachableMessage">
+                    [[numUnreachableMessage_]]
+                  </div>
+                </div>
+              </template>
               <template is="dom-repeat" items="[[contacts]]">
                 <div class="contact-item"
                     disabled$="[[isVisibility_(selectedVisibility,'none')]]">
diff --git a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js
index 1cd2597..8f6b1c8 100644
--- a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js
+++ b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js
@@ -108,6 +108,20 @@
       value: null,
     },
 
+    /** @private */
+    numUnreachable_: {
+      type: Number,
+      value: 0,
+      observer: 'updateNumUnreachableMessage_',
+    },
+
+    /** @private */
+    numUnreachableMessage_: {
+      type: String,
+      value: '',
+      notify: true,
+    },
+
     isVisibilitySelected: {
       type: Boolean,
       computed: 'isVisibilitySelected_(selectedVisibility)',
@@ -241,8 +255,12 @@
    *     the user so they can see who can see their device for visibility
    *     kAllContacts and so they can choose which contacts are
    *     |allowedContacts| for kSelectedContacts visibility.
+   * @param {number} numUnreachableExcluded the number of contact records that
+   *     are not reachable for Nearby Share. These are not included in the list
+   *     of contact records.
    */
-  onContactsDownloaded(allowedContacts, contactRecords) {
+  onContactsDownloaded(
+      allowedContacts, contactRecords, numUnreachableExcluded) {
     clearTimeout(this.downloadTimeoutId_);
 
     // TODO(vecore): Do a smart two-way merge that only splices actual changes.
@@ -257,6 +275,7 @@
     this.contacts = items;
     this.contactsState = items.length > 0 ? ContactsState.HAS_CONTACTS :
                                             ContactsState.ZERO_CONTACTS;
+    this.numUnreachable_ = numUnreachableExcluded;
   },
 
   /**
@@ -441,5 +460,32 @@
       this.downloadContacts_();
     });
   },
+
+  /**
+   * @return {boolean} true if the unreachable contacts message should be shown
+   * @private
+   */
+  showUnreachableContactsMessage_() {
+    return this.numUnreachable_ > 0;
+  },
+
+  /** @private */
+  updateNumUnreachableMessage_() {
+    if (this.numUnreachable_ === 0) {
+      this.numUnreachableMessage_ = '';
+      return;
+    }
+
+    // Template: "# contacts are not available." with correct plural of
+    // "contact".
+    const labelTemplate =
+        cr.sendWithPromise(
+              'getPluralString', 'nearbyShareContactVisibilityNumUnreachable',
+              this.numUnreachable_)
+            .then((labelTemplate) => {
+              this.numUnreachableMessage_ = loadTimeData.substituteString(
+                  labelTemplate, this.numUnreachable_);
+            });
+  },
 });
 })();
diff --git a/chrome/browser/resources/nearby_share/shared/nearby_shared.gni b/chrome/browser/resources/nearby_share/shared/nearby_shared.gni
index f2187b0..8ea9dd7f 100644
--- a/chrome/browser/resources/nearby_share/shared/nearby_shared.gni
+++ b/chrome/browser/resources/nearby_share/shared/nearby_shared.gni
@@ -7,6 +7,7 @@
   "chrome/browser/resources/nearby_share/shared/nearby_share_settings_behavior.html|NearbyShareSettingsBehavior,NearbySettings",
   "chrome/browser/resources/nearby_share/shared/nearby_contact_manager.html|getContactManager,observeContactManager",
   "ui/webui/resources/html/assert.html|assert,assertNotReached",
+  "ui/webui/resources/html/cr.html|sendWithPromise",
 ]
 
 nearby_shared_namespace_rewrites = [
diff --git a/chrome/browser/resources/new_tab_page/most_visited.html b/chrome/browser/resources/new_tab_page/most_visited.html
index 68476f25..1a90986 100644
--- a/chrome/browser/resources/new_tab_page/most_visited.html
+++ b/chrome/browser/resources/new_tab_page/most_visited.html
@@ -156,7 +156,7 @@
   .tile.dragging {
     background-color: var(--tile-hover-color);
     transition-property: none;
-    z-index: 1;
+    z-index: 2;
   }
 
   cr-icon-button {
diff --git a/chrome/browser/resources/new_tab_page/realbox.html b/chrome/browser/resources/new_tab_page/realbox.html
index 29a73fa..33b3ea83 100644
--- a/chrome/browser/resources/new_tab_page/realbox.html
+++ b/chrome/browser/resources/new_tab_page/realbox.html
@@ -90,11 +90,7 @@
   }
 
   ntp-realbox-dropdown {
-    border-radius: calc(0.25 * var(--ntp-realbox-height));
-    box-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
     left: 0;
-    padding-bottom: 8px;
-    padding-top: var(--ntp-realbox-height);
     position: absolute;
     right: 0;
     top: 0;
diff --git a/chrome/browser/resources/new_tab_page/realbox_dropdown.html b/chrome/browser/resources/new_tab_page/realbox_dropdown.html
index e64e8cf..76b2d69 100644
--- a/chrome/browser/resources/new_tab_page/realbox_dropdown.html
+++ b/chrome/browser/resources/new_tab_page/realbox_dropdown.html
@@ -1,19 +1,12 @@
 <style>
-  :host {
+  #selector {
     background-color: var(--search-box-results-bg, white);
-    overflow: hidden;
-  }
-
-  @media (min-width: 560px) {
-    :host {
-      width: 449px;
-    }
-  }
-
-  @media (min-width: 672px) {
-    :host {
-      width: 561px;
-    }
+    border-radius: calc(0.25 * var(--ntp-realbox-height));
+    box-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
+    display: block;
+    margin-bottom: 8px;
+    padding-bottom: 8px;
+    padding-top: var(--ntp-realbox-height);
   }
 
   ntp-realbox-match {
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index 2ee93e8..8b7bb8d 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
@@ -25,7 +26,7 @@
     ":pdf_resources",
     "elements:closure_compile",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "ink:closure_compile" ]
   }
 }
diff --git a/chrome/browser/resources/pdf/elements/BUILD.gn b/chrome/browser/resources/pdf/elements/BUILD.gn
index b42bf01..51e83ff 100644
--- a/chrome/browser/resources/pdf/elements/BUILD.gn
+++ b/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
@@ -24,7 +25,7 @@
     ":viewer-zoom-button",
     ":viewer-zoom-toolbar",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       ":viewer-annotations-bar",
       ":viewer-annotations-mode-dialog",
@@ -80,7 +81,7 @@
   ]
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   js_library("viewer-form-warning") {
     deps = [
       "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
@@ -211,7 +212,7 @@
     "viewer-zoom-button.js",
     "viewer-zoom-toolbar.js",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     js_files += [
       "viewer-annotations-bar.js",
       "viewer-annotations-mode-dialog.js",
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn
index ca34b38..f795e29 100644
--- a/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/common/features.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
@@ -108,7 +109,7 @@
     "ui/settings_behavior.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "native_layer_cros.js",
       "data/printer_status_cros.js",
@@ -161,7 +162,7 @@
     "ui/throbber_css.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "ui/destination_dropdown_cros.js",
       "ui/destination_select_cros.js",
diff --git a/chrome/browser/resources/print_preview/data/BUILD.gn b/chrome/browser/resources/print_preview/data/BUILD.gn
index 7753942..3fbcb62 100644
--- a/chrome/browser/resources/print_preview/data/BUILD.gn
+++ b/chrome/browser/resources/print_preview/data/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/polymer.gni")
 
@@ -100,7 +101,7 @@
     "//ui/webui/resources/js:load_time_data.m",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       ":destination_policies",
       "..:native_layer_cros",
diff --git a/chrome/browser/resources/print_preview/ui/BUILD.gn b/chrome/browser/resources/print_preview/ui/BUILD.gn
index 9a3971bd..904e464e 100644
--- a/chrome/browser/resources/print_preview/ui/BUILD.gn
+++ b/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
@@ -50,7 +51,7 @@
     ":sidebar",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       ":destination_dialog_cros",
       ":destination_dropdown_cros",
@@ -125,7 +126,7 @@
     "//ui/webui/resources/js:plural_string_proxy",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ ":pin_settings" ]
   }
 }
@@ -156,7 +157,7 @@
     "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       ":destination_dialog_cros",
       ":destination_select_cros",
@@ -169,7 +170,7 @@
   }
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   js_library("destination_select_cros") {
     deps = [
       ":destination_dropdown_cros",
@@ -448,7 +449,7 @@
   ]
 }
 
-if (is_chromeos) {
+if (is_chromeos_ash) {
   js_library("destination_dialog_cros") {
     deps = [
       ":destination_list",
@@ -599,7 +600,7 @@
     "sidebar.js",
     "throbber_css.js",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     js_files += [
       "destination_dialog_cros.js",
       "destination_dropdown_cros.js",
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 370ffbd..9d7ab0f6 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/common/features.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
@@ -131,7 +132,7 @@
     "site_settings/website_usage_browser_proxy.js",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [
       "autofill_page/blocking_request_manager.js",
       "languages_page/languages_metrics_proxy.js",
@@ -314,7 +315,7 @@
     in_files += [ "languages_page/edit_dictionary_page.js" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     in_files += [ "people_page/account_manager_browser_proxy.m.js" ]
   } else {
     in_files += [
@@ -358,7 +359,7 @@
     "settings_page:closure_compile",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "../../../test/data/webui/settings/chromeos:closure_compile",
       "chromeos:closure_compile",
@@ -451,7 +452,7 @@
     "site_settings:closure_compile_module",
     "site_settings_page:closure_compile_module",
   ]
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     deps += [
       "default_browser_page:closure_compile_module",
       "system_page:closure_compile_module",
@@ -465,7 +466,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "chromeos:closure_compile_module" ]
   }
 }
@@ -662,7 +663,7 @@
     ":web_components_local",
   ]
 
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     public_deps += [
       "default_browser_page:web_components",
       "system_page:web_components",
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn
index 817cbc9..11319551 100644
--- a/chrome/browser/resources/settings/people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 import("//tools/polymer/polymer.gni")
@@ -19,7 +20,7 @@
     ":sync_page",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ ":account_manager_browser_proxy" ]
   }
 }
@@ -112,7 +113,7 @@
     ":sync_page.m",
   ]
 
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     deps += [
       ":import_data_browser_proxy",
       ":import_data_dialog",
@@ -128,7 +129,7 @@
   extra_deps = [ ":modulize" ]
 }
 
-if (!is_chromeos) {
+if (!is_chromeos_ash) {
   js_library("import_data_browser_proxy") {
     deps = [ "//ui/webui/resources/js:cr.m" ]
     externs_list = [ "$externs_path/metrics_private.js" ]
@@ -279,7 +280,7 @@
 html_to_js("web_components") {
   js_files = [ "people_page.js" ]
 
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     js_files += [
       "import_data_dialog.js",
       "manage_profile.js",
diff --git a/chrome/browser/resources/signin/BUILD.gn b/chrome/browser/resources/signin/BUILD.gn
index 09f2e81..7be31ec 100644
--- a/chrome/browser/resources/signin/BUILD.gn
+++ b/chrome/browser/resources/signin/BUILD.gn
@@ -2,11 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//tools/polymer/html_to_js.gni")
 
 group("closure_compile") {
   deps = [ "sync_confirmation:closure_compile" ]
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     deps += [
       "dice_web_signin_intercept:closure_compile",
       "profile_customization:closure_compile",
@@ -23,7 +24,7 @@
     ":web_components_local",
     "sync_confirmation:web_components",
   ]
-  if (!is_chromeos) {
+  if (!is_chromeos_ash) {
     public_deps += [
       "dice_web_signin_intercept:web_components",
       "profile_customization:web_components",
diff --git a/chrome/browser/search/task_module/task_module_service.cc b/chrome/browser/search/task_module/task_module_service.cc
index b5df56bf..bb741eb 100644
--- a/chrome/browser/search/task_module/task_module_service.cc
+++ b/chrome/browser/search/task_module/task_module_service.cc
@@ -13,6 +13,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/search/ntp_features.h"
 #include "components/variations/net/variations_http_headers.h"
 #include "net/base/url_util.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -31,15 +32,33 @@
   }
 }
 
+// We return a reference so that base::FeatureList::CheckFeatureIdentity
+// succeeds.
+const base::Feature& GetFeature(
+    task_module::mojom::TaskModuleType task_module_type) {
+  switch (task_module_type) {
+    case task_module::mojom::TaskModuleType::kRecipe:
+      return ntp_features::kNtpRecipeTasksModule;
+    case task_module::mojom::TaskModuleType::kShopping:
+      return ntp_features::kNtpShoppingTasksModule;
+  }
+}
+
 GURL GetApiUrl(task_module::mojom::TaskModuleType task_module_type,
                const std::string& application_locale) {
   GURL google_base_url = google_util::CommandLineGoogleBaseURL();
   if (!google_base_url.is_valid()) {
     google_base_url = GURL(google_util::kGoogleHomepageURL);
   }
-  return net::AppendQueryParameter(
+  auto url = net::AppendQueryParameter(
       google_base_url.Resolve(GetPath(task_module_type)), "hl",
       application_locale);
+  if (base::GetFieldTrialParamValueByFeature(
+          GetFeature(task_module_type),
+          ntp_features::kNtpStatefulTasksModuleDataParam) == "fake") {
+    url = google_util::AppendToAsyncQueryParam(url, "fake_data", "1");
+  }
+  return url;
 }
 
 const char* GetTasksKey(task_module::mojom::TaskModuleType task_module_type) {
diff --git a/chrome/browser/sessions/session_restore_delegate.cc b/chrome/browser/sessions/session_restore_delegate.cc
index 21fd231..4b87a1b 100644
--- a/chrome/browser/sessions/session_restore_delegate.cc
+++ b/chrome/browser/sessions/session_restore_delegate.cc
@@ -78,6 +78,9 @@
 void SessionRestoreDelegate::RestoreTabs(
     const std::vector<RestoredTab>& tabs,
     const base::TimeTicks& restore_started) {
+  if (tabs.empty())
+    return;
+
   // Restore the favicon for all tabs. Any tab may end up being deferred due
   // to memory pressure so it's best to have some visual indication of its
   // contents.
@@ -89,6 +92,12 @@
                                  /*is_same_document=*/false);
   }
 
+  SessionRestoreStatsCollector::GetOrCreateInstance(
+      restore_started,
+      std::make_unique<
+          SessionRestoreStatsCollector::UmaStatsReportingDelegate>())
+      ->TrackTabs(tabs);
+
   // Don't start a TabLoader here if background tab loading is done by
   // PerformanceManager.
   if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc
index 29f2f82d..d3cd23b 100644
--- a/chrome/browser/sessions/tab_loader.cc
+++ b/chrome/browser/sessions/tab_loader.cc
@@ -14,7 +14,6 @@
 #include "base/time/default_tick_clock.h"
 #include "build/build_config.h"
 #include "chrome/browser/sessions/session_restore.h"
-#include "chrome/browser/sessions/session_restore_stats_collector.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "components/favicon/content/content_favicon_driver.h"
@@ -109,12 +108,6 @@
   if (!shared_tab_loader_)
     shared_tab_loader_ = new TabLoader();
 
-  SessionRestoreStatsCollector::GetOrCreateInstance(
-      restore_started,
-      std::make_unique<
-          SessionRestoreStatsCollector::UmaStatsReportingDelegate>())
-      ->TrackTabs(tabs);
-
   // TODO(chrisha): Mix overlapping session tab restore priorities. Right now
   // the lowest priority tabs from the first session restore will load before
   // the higher priority tabs from the next session restore.
diff --git a/chrome/browser/sharesheet/sharesheet_metrics.h b/chrome/browser/sharesheet/sharesheet_metrics.h
index 7ecd2ee..03d1256 100644
--- a/chrome/browser/sharesheet/sharesheet_metrics.h
+++ b/chrome/browser/sharesheet/sharesheet_metrics.h
@@ -14,7 +14,8 @@
   enum class UserAction {
     kCancelled = 0,  // User cancelled sharesheet.
     kArc,            // Opened an ARC app.
-    kMaxValue = kArc,
+    kAction,         // User selected an action.
+    kMaxValue = kAction,
   };
 
   SharesheetMetrics();
diff --git a/chrome/browser/sharesheet/sharesheet_service.cc b/chrome/browser/sharesheet/sharesheet_service.cc
index d35d977ec..73f4669 100644
--- a/chrome/browser/sharesheet/sharesheet_service.cc
+++ b/chrome/browser/sharesheet/sharesheet_service.cc
@@ -86,6 +86,8 @@
         sharesheet_action_cache_->GetActionFromName(target_name);
     if (share_action == nullptr)
       return;
+    sharesheet::SharesheetMetrics::RecordSharesheetActionMetrics(
+        sharesheet::SharesheetMetrics::UserAction::kAction);
     delegate->OnActionLaunched();
     share_action->LaunchAction(delegate, share_action_view, std::move(intent));
   } else if (type == TargetType::kApp) {
diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc
index 8c0099e..7863f7a8 100644
--- a/chrome/browser/signin/account_consistency_mode_manager.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager.cc
@@ -11,6 +11,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
@@ -21,7 +22,7 @@
 #include "components/signin/public/base/signin_pref_names.h"
 #include "google_apis/google_api_keys.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/account_manager/account_manager_util.h"
 #endif
 
@@ -172,7 +173,7 @@
 
 AccountConsistencyMethod
 AccountConsistencyModeManager::GetAccountConsistencyMethod() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO(https://crbug.com/860671): ChromeOS should use the cached value.
   // Changing the value dynamically is not supported.
   return ComputeAccountConsistencyMethod(profile_);
@@ -196,7 +197,7 @@
   return AccountConsistencyMethod::kMirror;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return chromeos::IsAccountManagerAvailable(profile)
              ? AccountConsistencyMethod::kMirror
              : AccountConsistencyMethod::kDisabled;
diff --git a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
index 454a0ef..6d8aa6eb 100644
--- a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/scoped_command_line.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/common/pref_names.h"
@@ -42,7 +43,7 @@
   std::unique_ptr<TestingProfile> profile =
       BuildTestingProfile(/*is_new_profile=*/false);
 
-#if BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_MIRROR) || BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(signin::AccountConsistencyMethod::kMirror,
             AccountConsistencyModeManager::GetMethodForProfile(profile.get()));
   EXPECT_TRUE(
@@ -238,7 +239,7 @@
 }
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Mirror is enabled by default on Chrome OS, unless specified otherwise.
 TEST(AccountConsistencyModeManagerTest, MirrorEnabledByDefault) {
   // Creation of this object sets the current thread's id as UI thread.
@@ -290,7 +291,7 @@
   EXPECT_EQ(signin::AccountConsistencyMethod::kDisabled,
             AccountConsistencyModeManager::GetMethodForProfile(otr_profile));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_MIRROR)
 // Test that Mirror is enabled for child accounts.
diff --git a/chrome/browser/signin/account_id_from_account_info.cc b/chrome/browser/signin/account_id_from_account_info.cc
index f6223e6..c801c7a 100644
--- a/chrome/browser/signin/account_id_from_account_info.cc
+++ b/chrome/browser/signin/account_id_from_account_info.cc
@@ -3,14 +3,15 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/signin/account_id_from_account_info.h"
+#include "build/chromeos_buildflags.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/user_manager/known_user.h"
 #endif
 
 AccountId AccountIdFromAccountInfo(const CoreAccountInfo& account_info) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return user_manager::known_user::GetAccountId(
       account_info.email, account_info.gaia, AccountType::GOOGLE);
 #else
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index e942b63..5378440 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -11,6 +11,7 @@
 #include "base/feature_list.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
@@ -22,7 +23,7 @@
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/account_manager/account_manager_migrator.h"
@@ -44,7 +45,7 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class ChromeOSLimitedAccessAccountReconcilorDelegate
     : public signin::MirrorAccountReconcilorDelegate {
  public:
@@ -142,7 +143,7 @@
 
   DISALLOW_COPY_AND_ASSIGN(ChromeOSAccountReconcilorDelegate);
 };
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
 
@@ -183,7 +184,7 @@
 
 void AccountReconcilorFactory::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterBooleanPref(prefs::kForceLogoutUnauthenticatedUserEnabled,
                                 false);
 #endif
@@ -196,7 +197,7 @@
       AccountConsistencyModeManager::GetMethodForProfile(profile);
   switch (account_consistency) {
     case signin::AccountConsistencyMethod::kMirror:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       // Only for child accounts on Chrome OS, use the specialized Mirror
       // delegate.
       if (profile->IsChild()) {
diff --git a/chrome/browser/signin/chrome_device_id_helper.cc b/chrome/browser/signin/chrome_device_id_helper.cc
index 1f38b72..8202308 100644
--- a/chrome/browser/signin/chrome_device_id_helper.cc
+++ b/chrome/browser/signin/chrome_device_id_helper.cc
@@ -6,10 +6,11 @@
 
 #include <string>
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/signin/public/base/device_id_helper.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/command_line.h"
 #include "base/guid.h"
 #include "base/logging.h"
@@ -22,7 +23,7 @@
 #endif
 
 std::string GetSigninScopedDeviceIdForProfile(Profile* profile) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableSigninScopedDeviceId)) {
     return std::string();
@@ -47,7 +48,7 @@
 #endif
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::string GenerateSigninScopedDeviceId(bool for_ephemeral) {
   constexpr char kEphemeralUserDeviceIDPrefix[] = "t_";
diff --git a/chrome/browser/signin/chrome_device_id_helper.h b/chrome/browser/signin/chrome_device_id_helper.h
index b899ea15..9e84d41 100644
--- a/chrome/browser/signin/chrome_device_id_helper.h
+++ b/chrome/browser/signin/chrome_device_id_helper.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 class Profile;
 
@@ -18,7 +19,7 @@
 //     signin::GetSigninScopedDeviceId(profile->GetPrefs());
 std::string GetSigninScopedDeviceIdForProfile(Profile* profile);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Helper method. The device ID should generally be obtained through
 // GetSigninScopedDeviceIdForProfile().
diff --git a/chrome/browser/signin/chrome_device_id_helper_unittest.cc b/chrome/browser/signin/chrome_device_id_helper_unittest.cc
index 8caeca79..3e2f2e9 100644
--- a/chrome/browser/signin/chrome_device_id_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_device_id_helper_unittest.cc
@@ -8,9 +8,10 @@
 
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kEpehemeralPrefix[] = "t_";
 
 TEST(DeviceIdHelper, NotEphemeral) {
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 640cdd4..8da6a384 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -50,7 +51,7 @@
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/net/delay_network_call.h"
 #endif
 
@@ -59,7 +60,7 @@
 #include "chrome/browser/profiles/profile_window.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/user_manager.h"
 #endif
@@ -94,13 +95,13 @@
 }  // namespace
 
 ChromeSigninClient::ChromeSigninClient(Profile* profile) : profile_(profile) {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this);
 #endif
 }
 
 ChromeSigninClient::~ChromeSigninClient() {
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this);
 #endif
 }
@@ -162,7 +163,7 @@
   DCHECK(!on_signout_decision_reached_) << "SignOut already in-progress!";
   on_signout_decision_reached_ = std::move(on_signout_decision_reached);
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // These sign out won't remove the policy cache, keep the window opened.
   bool keep_window_opened =
@@ -242,7 +243,7 @@
   oauth_client_->GetTokenInfo(access_token_info.token, 3 /* retries */, this);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void ChromeSigninClient::OnConnectionChanged(
     network::mojom::ConnectionType type) {
   if (type == network::mojom::ConnectionType::CONNECTION_NONE)
@@ -256,7 +257,7 @@
 #endif
 
 void ChromeSigninClient::DelayNetworkCall(base::OnceClosure callback) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::DelayNetworkCall(
       base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
       std::move(callback));
@@ -284,7 +285,7 @@
 }
 
 void ChromeSigninClient::VerifySyncToken() {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   // We only verifiy the token once when Profile is just created.
   if (signin_util::IsForceSigninEnabled() && !force_signin_verifier_)
     force_signin_verifier_ = std::make_unique<ForceSigninVerifier>(
@@ -293,7 +294,7 @@
 }
 
 void ChromeSigninClient::MaybeFetchSigninTokenHandle() {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   // We get a "handle" that can be used to reference the signin token on the
   // server.  We fetch this if we don't have one so that later we can check
   // it to know if the signin token to which it is attached has been revoked
@@ -343,7 +344,7 @@
 void ChromeSigninClient::OnCloseBrowsersSuccess(
     const signin_metrics::ProfileSignout signout_source_metric,
     const base::FilePath& profile_path) {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   if (signin_util::IsForceSigninEnabled() && force_signin_verifier_.get()) {
     force_signin_verifier_->Cancel();
   }
@@ -383,7 +384,7 @@
 }
 
 void ChromeSigninClient::ShowUserManager(const base::FilePath& profile_path) {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   UserManager::Show(profile_path,
                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
 #endif
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index 32f71fa..ecc45caf 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -14,24 +14,25 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/network_change_manager.mojom-forward.h"
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "services/network/public/cpp/network_connection_tracker.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
 class ForceSigninVerifier;
 #endif
 class Profile;
 
 class ChromeSigninClient
     : public SigninClient,
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
       public network::NetworkConnectionTracker::NetworkConnectionObserver,
 #endif
       public gaia::GaiaOAuthClient::Delegate {
@@ -69,7 +70,7 @@
   void OnOAuthError() override;
   void OnNetworkError(int response_code) override;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // network::NetworkConnectionTracker::NetworkConnectionObserver
   // implementation.
   void OnConnectionChanged(network::mojom::ConnectionType type) override;
@@ -103,12 +104,12 @@
   // Stored callback from PreSignOut();
   base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached_;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   std::list<base::OnceClosure> delayed_callbacks_;
 #endif
 
   bool should_display_user_manager_ = true;
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<ForceSigninVerifier> force_signin_verifier_;
 #endif
 
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc
index 577ed30..133e857 100644
--- a/chrome/browser/signin/chrome_signin_client_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/signin_util.h"
@@ -28,7 +29,7 @@
 #endif
 
 // ChromeOS has its own network delay logic.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -335,4 +336,4 @@
                          testing::ValuesIn(kSignoutSources));
 
 #endif  // !defined(OS_ANDROID)
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 26fed939..2355b3cd 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -18,6 +18,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_io_data.h"
@@ -56,7 +57,7 @@
 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
@@ -170,7 +171,7 @@
 void ProcessMirrorHeader(
     ManageAccountsParams manage_accounts_params,
     const content::WebContents::Getter& web_contents_getter) {
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   GAIAServiceType service_type = manage_accounts_params.service_type;
@@ -188,7 +189,7 @@
   AccountReconcilor* account_reconcilor =
       AccountReconcilorFactory::GetForProfile(profile);
   account_reconcilor->OnReceivedManageAccountsResponse(service_type);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
       account_reconcilor->GetState());
 
@@ -292,7 +293,7 @@
       profile, chromeos::settings::mojom::kMyAccountsSubpagePath);
   return;
 
-#else   // !defined(OS_CHROMEOS)
+#else   // !BUILDFLAG(IS_CHROMEOS_ASH)
   if (manage_accounts_params.show_consistency_promo &&
       base::FeatureList::IsEnabled(kMobileIdentityConsistency)) {
     auto* window = web_contents->GetNativeView()->GetWindowAndroid();
@@ -323,8 +324,8 @@
     SigninUtils::OpenAccountManagementScreen(window, service_type,
                                              manage_accounts_params.email);
   }
-#endif  // defined(OS_CHROMEOS)
-#endif  // defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
 }
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -506,7 +507,7 @@
     AccountConsistencyMethod account_consistency,
     std::string gaia_id,
     const base::Optional<bool>& is_child_account,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     bool is_secondary_account_addition_allowed,
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -523,7 +524,7 @@
     profile_mode_mask |= PROFILE_MODE_INCOGNITO_DISABLED;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!is_secondary_account_addition_allowed) {
     account_consistency = AccountConsistencyMethod::kMirror;
     // Can't add new accounts.
diff --git a/chrome/browser/signin/chrome_signin_helper.h b/chrome/browser/signin/chrome_signin_helper.h
index eca856d..d1c82f9 100644
--- a/chrome/browser/signin/chrome_signin_helper.h
+++ b/chrome/browser/signin/chrome_signin_helper.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/supports_user_data.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "content/public/browser/web_contents.h"
@@ -96,7 +97,7 @@
     AccountConsistencyMethod account_consistency,
     std::string gaia_id,
     const base::Optional<bool>& is_child_account,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     bool is_secondary_account_addition_allowed,
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index 3b743d4..3a72e5a 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "content/public/test/browser_task_environment.h"
@@ -25,7 +26,7 @@
 
 namespace {
 
-#if BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_MIRROR) || BUILDFLAG(IS_CHROMEOS_ASH)
 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts";
 const char kMirrorAction[] = "action=ADDSESSION";
 #endif
@@ -130,7 +131,7 @@
 }
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
-#if BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_MIRROR) || BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests that user data is set on Mirror requests.
 TEST_F(ChromeSigninHelperTest, MirrorMainFrame) {
   // Process the header.
@@ -159,4 +160,4 @@
   EXPECT_FALSE(response_adapter.GetUserData(
       signin::kManageAccountsHeaderReceivedUserDataKey));
 }
-#endif  // BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(ENABLE_MIRROR) || BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
index 67bb6ca..808569a 100644
--- a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
+++ b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
@@ -6,6 +6,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
@@ -31,9 +32,9 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/sync/sync_ui_util.h"
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace signin {
 namespace test {
@@ -326,10 +327,10 @@
   EXPECT_TRUE(
       identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
           primary_account.account_id));
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_EQ(sync_ui_util::GetAvatarSyncErrorType(browser()->profile()),
             sync_ui_util::AUTH_ERROR);
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // This test can pass. Marked as manual because it TIMED_OUT on Win7.
diff --git a/chrome/browser/signin/e2e_tests/test_accounts_util.cc b/chrome/browser/signin/e2e_tests/test_accounts_util.cc
index e9318aca..c533ea0f 100644
--- a/chrome/browser/signin/e2e_tests/test_accounts_util.cc
+++ b/chrome/browser/signin/e2e_tests/test_accounts_util.cc
@@ -9,6 +9,7 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_reader.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 using base::Value;
 
@@ -19,9 +20,9 @@
 std::string kPlatform = "win";
 #elif defined(OS_MAC)
 std::string kPlatform = "mac";
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
 std::string kPlatform = "chromeos";
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 std::string kPlatform = "linux";
 #elif defined(OS_ANDROID)
 std::string kPlatform = "android";
diff --git a/chrome/browser/signin/header_modification_delegate_impl.cc b/chrome/browser/signin/header_modification_delegate_impl.cc
index 50fc0672..0a1212b 100644
--- a/chrome/browser/signin/header_modification_delegate_impl.cc
+++ b/chrome/browser/signin/header_modification_delegate_impl.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/signin/header_modification_delegate_impl.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
 #include "chrome/browser/profiles/profile_io_data.h"
@@ -23,7 +24,7 @@
 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_pref_names.h"
 #endif
 
@@ -58,7 +59,7 @@
       ProfileSyncServiceFactory::GetForProfile(profile_);
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool is_secondary_account_addition_allowed = true;
   if (!prefs->GetBoolean(
           chromeos::prefs::kSecondaryGoogleAccountSigninAllowed)) {
@@ -92,7 +93,7 @@
       prefs->GetInteger(prefs::kIncognitoModeAvailability),
       AccountConsistencyModeManager::GetMethodForProfile(profile_),
       account.gaia, is_child_account,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       is_secondary_account_addition_allowed,
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
diff --git a/chrome/browser/signin/identity_manager_factory.cc b/chrome/browser/signin/identity_manager_factory.cc
index 25aaf8e..10b6d90b 100644
--- a/chrome/browser/signin/identity_manager_factory.cc
+++ b/chrome/browser/signin/identity_manager_factory.cc
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/image_fetcher/image_decoder_impl.h"
 #include "chrome/browser/profiles/profile.h"
@@ -30,7 +31,7 @@
 #include "components/signin/core/browser/cookie_settings_util.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
@@ -114,7 +115,7 @@
       profile, ServiceAccessType::EXPLICIT_ACCESS);
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory* factory =
       g_browser_process->platform_part()->GetAccountManagerFactory();
   DCHECK(factory);
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
index 7f35c77..581ca67 100644
--- a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
+++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
@@ -5,10 +5,11 @@
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
 
 #include "base/bind.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
@@ -77,7 +78,7 @@
 IdentityTestEnvironmentProfileAdaptor::BuildIdentityManagerForTests(
     content::BrowserContext* context) {
   Profile* profile = Profile::FromBrowserContext(context);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return signin::IdentityTestEnvironment::BuildIdentityManagerForTests(
       ChromeSigninClientFactory::GetForProfile(profile), profile->GetPrefs(),
       profile->GetPath(),
diff --git a/chrome/browser/signin/signin_error_controller_factory.cc b/chrome/browser/signin/signin_error_controller_factory.cc
index cbc4d140..ebbd061 100644
--- a/chrome/browser/signin/signin_error_controller_factory.cc
+++ b/chrome/browser/signin/signin_error_controller_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/signin/signin_error_controller_factory.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -35,7 +36,7 @@
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
   SigninErrorController::AccountMode account_mode =
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       SigninErrorController::AccountMode::ANY_ACCOUNT;
 #else
       AccountConsistencyModeManager::IsMirrorEnabledForProfile(profile)
diff --git a/chrome/browser/signin/signin_global_error.cc b/chrome/browser/signin/signin_global_error.cc
index f80f1223..a85eae903e 100644
--- a/chrome/browser/signin/signin_global_error.cc
+++ b/chrome/browser/signin/signin_global_error.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -68,7 +69,7 @@
 }
 
 void SigninGlobalError::ExecuteMenuItem(Browser* browser) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (error_controller_->auth_error().state() !=
       GoogleServiceAuthError::NONE) {
     DVLOG(1) << "Signing out the user to fix a sync error.";
diff --git a/chrome/browser/signin/signin_global_error_factory.cc b/chrome/browser/signin/signin_global_error_factory.cc
index b2255a4f..304d6a5 100644
--- a/chrome/browser/signin/signin_global_error_factory.cc
+++ b/chrome/browser/signin/signin_global_error_factory.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/signin/signin_global_error_factory.h"
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
@@ -35,7 +36,7 @@
 
 KeyedService* SigninGlobalErrorFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return nullptr;
 #endif
 
diff --git a/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc b/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc
index 4aee345..0349152 100644
--- a/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc
+++ b/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/signin/signin_util.h"
@@ -26,7 +27,7 @@
 namespace {
 const char kEmail[] = "example@email.com";
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void CheckProfilePrefsReset(PrefService* pref_service,
                             bool expected_using_default_name) {
   EXPECT_TRUE(pref_service->GetBoolean(prefs::kProfileUsingDefaultAvatar));
@@ -51,7 +52,7 @@
 
   CheckProfilePrefsSet(pref_service, false);
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }  // namespace
 
 class SigninProfileAttributesUpdaterTest : public testing::Test {
@@ -93,7 +94,7 @@
       signin_profile_attributes_updater_;
 };
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests that the browser state info is updated on signin and signout.
 // ChromeOS does not support signout.
 TEST_F(SigninProfileAttributesUpdaterTest, SigninSignout) {
@@ -114,7 +115,7 @@
   EXPECT_EQ(entry->GetSigninState(), SigninState::kNotSignedIn);
   EXPECT_FALSE(entry->IsSigninRequired());
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Tests that the browser state info is updated on auth error change.
 TEST_F(SigninProfileAttributesUpdaterTest, AuthError) {
@@ -125,7 +126,7 @@
   CoreAccountId account_id =
       identity_test_env_.MakePrimaryAccountAvailable(kEmail).account_id;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // ChromeOS only observes signin state at initial creation of the updater, so
   // recreate the updater after having set the primary account.
   RecreateSigninProfileAttributesUpdater();
@@ -146,7 +147,7 @@
   EXPECT_FALSE(entry->IsAuthError());
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(SigninProfileAttributesUpdaterTest, SigninSignoutResetsProfilePrefs) {
   PrefService* pref_service = profile_->GetPrefs();
   ProfileAttributesEntry* entry;
@@ -253,4 +254,4 @@
   EXPECT_EQ(entry->GetSigninState(), SigninState::kNotSignedIn);
   EXPECT_TRUE(entry->IsSigninRequired());
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc
index 5e4ce29..22bb3c2fd 100644
--- a/chrome/browser/signin/signin_promo.cc
+++ b/chrome/browser/signin/signin_promo.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/signin/signin_promo.h"
 
 #include "base/strings/string_number_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/google/google_brand.h"
@@ -34,7 +35,7 @@
 const char kSignInPromoQueryKeyForceKeepData[] = "force_keep_data";
 const char kSignInPromoQueryKeyReason[] = "reason";
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 GURL GetEmbeddedPromoURL(signin_metrics::AccessPoint access_point,
                          signin_metrics::Reason reason,
                          bool auto_close) {
@@ -69,7 +70,7 @@
   url = net::AppendQueryParameter(url, "validateEmail", "1");
   return net::AppendQueryParameter(url, "readOnlyEmail", "1");
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 GURL GetChromeSyncURLForDice(const std::string& email,
                              const std::string& continue_url) {
diff --git a/chrome/browser/signin/signin_promo.h b/chrome/browser/signin/signin_promo.h
index d054e965..9a3fe0c5 100644
--- a/chrome/browser/signin/signin_promo.h
+++ b/chrome/browser/signin/signin_promo.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/signin_metrics.h"
 
 class GURL;
@@ -29,7 +30,7 @@
 extern const char kSignInPromoQueryKeyForceKeepData[];
 extern const char kSignInPromoQueryKeyReason[];
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // These functions are only used to unlock the profile from the desktop user
 // manager and the windows credential provider.
 
@@ -47,7 +48,7 @@
 GURL GetEmbeddedReauthURLWithEmail(signin_metrics::AccessPoint access_point,
                                    signin_metrics::Reason reason,
                                    const std::string& email);
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Returns the URL to be used to signin and turn on Sync when DICE is enabled.
 // If email is not empty, then it will pass email as hint to the page so that it
diff --git a/chrome/browser/signin/signin_promo_unittest.cc b/chrome/browser/signin/signin_promo_unittest.cc
index 4dccae23..28c3b9a 100644
--- a/chrome/browser/signin/signin_promo_unittest.cc
+++ b/chrome/browser/signin/signin_promo_unittest.cc
@@ -5,13 +5,14 @@
 #include "chrome/browser/signin/signin_promo.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/webui_url_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 namespace signin {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST(SigninPromoTest, TestPromoURL) {
   GURL::Replacements replace_query;
   replace_query.SetQueryStr("access_point=0&reason=0&auto_close=1");
@@ -40,7 +41,7 @@
           signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
           signin_metrics::Reason::REASON_UNLOCK, "example@domain.com"));
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST(SigninPromoTest, SigninURLForDice) {
   EXPECT_EQ(
diff --git a/chrome/browser/signin/signin_promo_util.cc b/chrome/browser/signin/signin_promo_util.cc
index ad49d90..fb7dcf4 100644
--- a/chrome/browser/signin/signin_promo_util.cc
+++ b/chrome/browser/signin/signin_promo_util.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/signin/signin_promo_util.h"
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/prefs/pref_service.h"
@@ -15,7 +16,7 @@
 namespace signin {
 
 bool ShouldShowPromo(Profile* profile) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // There's no need to show the sign in promo on cros since cros users are
   // already logged in.
   return false;
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index 7c186aa..3970e51 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -19,6 +19,7 @@
 #include "base/supports_user_data.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -41,7 +42,7 @@
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/text_elider.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #endif
 
@@ -169,14 +170,14 @@
   auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
   if (identity_manager->HasPrimaryAccount()) {
     user_display_name = identity_manager->GetPrimaryAccountInfo().email;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // See https://crbug.com/994798 for details.
     user_manager::User* user =
         chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
     // |user| may be null in tests.
     if (user)
       user_display_name = user->GetDisplayEmail();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   return base::UTF8ToUTF16(user_display_name);
@@ -247,7 +248,8 @@
   }
 
   if (account.IsEmpty()) {
-    chrome::ShowBrowserSignin(browser, access_point);
+    chrome::ShowBrowserSignin(browser, access_point,
+                              signin::ConsentLevel::kSync);
     return;
   }
 
diff --git a/chrome/browser/signin/signin_util.cc b/chrome/browser/signin/signin_util.cc
index b24855d..7e1add74 100644
--- a/chrome/browser/signin/signin_util.cc
+++ b/chrome/browser/signin/signin_util.cc
@@ -12,6 +12,7 @@
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/cloud/user_policy_signin_service_internal.h"
 #include "chrome/browser/profiles/profile.h"
@@ -211,7 +212,7 @@
 void EnsurePrimaryAccountAllowedForProfile(Profile* profile) {
 // All primary accounts are allowed on ChromeOS, so this method is a no-op on
 // ChromeOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
   if (!identity_manager->HasPrimaryAccount())
     return;
@@ -257,7 +258,7 @@
 #endif  // defined(CAN_DELETE_PROFILE)
       break;
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 // TODO(crbug.com/1134111): Remove GuestSignedInUserData when Ephemeral Guest
diff --git a/chrome/browser/ssl/sct_reporting_service_browsertest.cc b/chrome/browser/ssl/sct_reporting_service_browsertest.cc
index b0f82cf4..908242d4 100644
--- a/chrome/browser/ssl/sct_reporting_service_browsertest.cc
+++ b/chrome/browser/ssl/sct_reporting_service_browsertest.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/ssl/sct_reporting_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
@@ -24,6 +23,8 @@
 #include "content/public/test/content_mock_cert_verifier.h"
 #include "content/public/test/network_service_test_helper.h"
 #include "net/cert/cert_verify_result.h"
+#include "net/cert/sct_status_flags.h"
+#include "net/cert/signed_certificate_timestamp_and_status.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"
@@ -33,6 +34,54 @@
 #include "services/network/public/proto/sct_audit_report.pb.h"
 #include "services/network/test/test_url_loader_factory.h"
 
+namespace {
+
+// These LogId constants allow test cases to specify SCTs from both Google and
+// non-Google logs, allowing tests to vary how they meet (or don't meet) the
+// Chrome CT policy. To be compliant, the cert used by the embedded test server
+// currently requires three embedded SCTs, including at least one from a Google
+// log and one from a non-Google log.
+//
+// Google's "Argon2023" log ("6D7Q2j71BjUy51covIlryQPTy9ERa+zraeF3fW0GvW4="):
+const char kTestGoogleLogId[] = {
+    0xe8, 0x3e, 0xd0, 0xda, 0x3e, 0xf5, 0x06, 0x35, 0x32, 0xe7, 0x57,
+    0x28, 0xbc, 0x89, 0x6b, 0xc9, 0x03, 0xd3, 0xcb, 0xd1, 0x11, 0x6b,
+    0xec, 0xeb, 0x69, 0xe1, 0x77, 0x7d, 0x6d, 0x06, 0xbd, 0x6e};
+// Cloudflare's "Nimbus2023" log
+// ("ejKMVNi3LbYg6jjgUh7phBZwMhOFTTvSK8E6V6NS61I="):
+const char kTestNonGoogleLogId1[] = {
+    0x7a, 0x32, 0x8c, 0x54, 0xd8, 0xb7, 0x2d, 0xb6, 0x20, 0xea, 0x38,
+    0xe0, 0x52, 0x1e, 0xe9, 0x84, 0x16, 0x70, 0x32, 0x13, 0x85, 0x4d,
+    0x3b, 0xd2, 0x2b, 0xc1, 0x3a, 0x57, 0xa3, 0x52, 0xeb, 0x52};
+// DigiCert's "Yeti2023" log ("Nc8ZG7+xbFe/D61MbULLu7YnICZR6j/hKu+oA8M71kw="):
+const char kTestNonGoogleLogId2[] = {
+    0x35, 0xcf, 0x19, 0x1b, 0xbf, 0xb1, 0x6c, 0x57, 0xbf, 0x0f, 0xad,
+    0x4c, 0x6d, 0x42, 0xcb, 0xbb, 0xb6, 0x27, 0x20, 0x26, 0x51, 0xea,
+    0x3f, 0xe1, 0x2a, 0xef, 0xa8, 0x03, 0xc3, 0x3b, 0xd6, 0x4c};
+
+// Constructs a net::SignedCertificateTimestampAndStatus with the given
+// information and appends it to |sct_list|.
+void MakeTestSCTAndStatus(
+    net::ct::SignedCertificateTimestamp::Origin origin,
+    const std::string& extensions,
+    const std::string& signature_data,
+    const base::Time& timestamp,
+    const std::string& log_id,
+    net::ct::SCTVerifyStatus status,
+    net::SignedCertificateTimestampAndStatusList* sct_list) {
+  scoped_refptr<net::ct::SignedCertificateTimestamp> sct(
+      new net::ct::SignedCertificateTimestamp());
+  sct->version = net::ct::SignedCertificateTimestamp::V1;
+  sct->log_id = log_id;
+  sct->extensions = extensions;
+  sct->timestamp = timestamp;
+  sct->signature.signature_data = signature_data;
+  sct->origin = origin;
+  sct_list->push_back(net::SignedCertificateTimestampAndStatus(sct, status));
+}
+
+}  // namespace
+
 class SCTReportingServiceBrowserTest : public CertVerifierBrowserTest {
  public:
   SCTReportingServiceBrowserTest() {
@@ -68,10 +117,31 @@
     report_server()->StartAcceptingConnections();
     ASSERT_TRUE(https_server()->Start());
 
-    // Set up two test hosts as using publicly-issued certificates for testing.
+    // Mock the cert verify results so that it has valid CT verification
+    // results.
     net::CertVerifyResult verify_result;
-    verify_result.verified_cert = https_server_.GetCertificate().get();
+    verify_result.verified_cert = https_server()->GetCertificate().get();
     verify_result.is_issued_by_known_root = true;
+    // Add three "valid" SCTs and mark the certificate as compliant.
+    // The default test set up is embedded SCTs where one SCT is from a Google
+    // log and two are from non-Google logs (to meet the Chrome CT policy).
+    MakeTestSCTAndStatus(
+        net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions1",
+        "signature1", base::Time::Now(),
+        std::string(kTestGoogleLogId, base::size(kTestGoogleLogId)),
+        net::ct::SCT_STATUS_OK, &verify_result.scts);
+    MakeTestSCTAndStatus(
+        net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions2",
+        "signature2", base::Time::Now(),
+        std::string(kTestNonGoogleLogId1, base::size(kTestNonGoogleLogId1)),
+        net::ct::SCT_STATUS_OK, &verify_result.scts);
+    MakeTestSCTAndStatus(
+        net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions3",
+        "signature3", base::Time::Now(),
+        std::string(kTestNonGoogleLogId2, base::size(kTestNonGoogleLogId2)),
+        net::ct::SCT_STATUS_OK, &verify_result.scts);
+
+    // Set up two test hosts as using publicly-issued certificates for testing.
     mock_cert_verifier()->AddResultForCertAndHost(
         https_server()->GetCertificate().get(), "a.test", verify_result,
         net::OK);
@@ -113,12 +183,11 @@
 
   size_t requests_seen() { return requests_seen_; }
 
-  std::string GetLastSeenHostname() {
-    if (!last_seen_request_.has_content)
-      return std::string();
+  sct_auditing::TLSConnectionReport GetLastSeenReport() {
     sct_auditing::TLSConnectionReport auditing_report;
-    auditing_report.ParseFromString(last_seen_request_.content);
-    return auditing_report.context().origin().hostname();
+    if (last_seen_request_.has_content)
+      auditing_report.ParseFromString(last_seen_request_.content);
+    return auditing_report;
   }
 
   // Checks that no reports have been sent. To do this, opt-in the profile,
@@ -133,7 +202,8 @@
         https_server()->GetURL("flush-and-check-zero-reports.test", "/"));
     WaitForRequests(1);
     return (1u == requests_seen() &&
-            "flush-and-check-zero-reports.test" == GetLastSeenHostname());
+            "flush-and-check-zero-reports.test" ==
+                GetLastSeenReport().context().origin().hostname());
   }
 
  private:
@@ -188,7 +258,7 @@
 
   // Check that one report was sent and contains the expected details.
   EXPECT_EQ(1u, requests_seen());
-  EXPECT_EQ("a.test", GetLastSeenHostname());
+  EXPECT_EQ("a.test", GetLastSeenReport().context().origin().hostname());
 }
 
 // Tests that disabling Safe Browsing entirely should cause reports to not get
@@ -242,7 +312,7 @@
 
   // Check that one report was sent.
   EXPECT_EQ(1u, requests_seen());
-  EXPECT_EQ("a.test", GetLastSeenHostname());
+  EXPECT_EQ("a.test", GetLastSeenReport().context().origin().hostname());
 
   // Disable Extended Reporting which should clear the underlying cache.
   SetExtendedReportingEnabled(false);
@@ -254,7 +324,7 @@
                                https_server()->GetURL("a.test", "/"));
   WaitForRequests(2);
   EXPECT_EQ(2u, requests_seen());
-  EXPECT_EQ("a.test", GetLastSeenHostname());
+  EXPECT_EQ("a.test", GetLastSeenReport().context().origin().hostname());
 }
 
 // Tests that reports are still sent for opted-in profiles after the network
@@ -282,6 +352,21 @@
   net::CertVerifyResult verify_result;
   verify_result.verified_cert = https_server()->GetCertificate().get();
   verify_result.is_issued_by_known_root = true;
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions1",
+      "signature1", base::Time::Now(),
+      std::string(kTestGoogleLogId, base::size(kTestGoogleLogId)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions2",
+      "signature2", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, base::size(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions3",
+      "signature3", base::Time::Now(),
+      std::string(kTestNonGoogleLogId2, base::size(kTestNonGoogleLogId2)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
   mock_cert_verifier()->AddResultForCertAndHost(
       https_server()->GetCertificate().get(), "a.test", verify_result, net::OK);
 
@@ -292,33 +377,125 @@
 
   // Check that one report was enqueued.
   EXPECT_EQ(1u, requests_seen());
-  EXPECT_EQ("a.test", GetLastSeenHostname());
+  EXPECT_EQ("a.test", GetLastSeenReport().context().origin().hostname());
 }
 
-// Tests that certificates that aren't issued from publicly known roots don't
-// get reported.
+// Tests that invalid SCTs don't get reported when the overall result is
+// compliant with CT policy.
 IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
-                       PrivateCertsNotReported) {
-  // Set up a hostname that uses a non-publicly issued cert.
+                       CTCompliantInvalidSCTsNotReported) {
+  // Set up a mocked CertVerifyResult that includes both valid and invalid SCTs.
   net::CertVerifyResult verify_result;
   verify_result.verified_cert = https_server()->GetCertificate().get();
-  verify_result.is_issued_by_known_root = false;
+  verify_result.is_issued_by_known_root = true;
+  // Add three valid SCTs and one invalid SCT. The three valid SCTs meet the
+  // Chrome CT policy.
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "extensions1", "signature1", base::Time::Now(),
+                       std::string(kTestGoogleLogId, sizeof(kTestGoogleLogId)),
+                       net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions2",
+      "signature2", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions3",
+      "signature3", base::Time::Now(),
+      std::string(kTestNonGoogleLogId2, sizeof(kTestNonGoogleLogId2)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions4",
+      "signature4", base::Time::Now(),
+      std::string(kTestNonGoogleLogId2, sizeof(kTestNonGoogleLogId2)),
+      net::ct::SCT_STATUS_INVALID_SIGNATURE, &verify_result.scts);
+
   mock_cert_verifier()->AddResultForCertAndHost(
-      https_server()->GetCertificate().get(), "private.test", verify_result,
+      https_server()->GetCertificate().get(), "mixed-scts.test", verify_result,
       net::OK);
 
   SetExtendedReportingEnabled(true);
   ui_test_utils::NavigateToURL(browser(),
-                               https_server()->GetURL("private.test", "/"));
+                               https_server()->GetURL("mixed-scts.test", "/"));
+  WaitForRequests(1);
+  EXPECT_EQ(1u, requests_seen());
 
+  auto report = GetLastSeenReport();
+  EXPECT_EQ(3, report.included_scts_size());
+}
+
+// Tests that invalid SCTs don't get included when the overall result is
+// non-compliant with CT policy. Valid SCTs should still be reported.
+IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
+                       CTNonCompliantInvalidSCTsNotReported) {
+  // Set up a mocked CertVerifyResult that includes both valid and invalid SCTs.
+  net::CertVerifyResult verify_result;
+  verify_result.verified_cert = https_server()->GetCertificate().get();
+  verify_result.is_issued_by_known_root = true;
+  // Add one valid SCT and two invalid SCTs. These SCTs will not meet the Chrome
+  // CT policy requirements.
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions1",
+      "signature1", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_OK, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions2",
+      "signature2", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_INVALID_SIGNATURE, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions3",
+      "signature3", base::Time::Now(),
+      std::string(kTestNonGoogleLogId2, sizeof(kTestNonGoogleLogId2)),
+      net::ct::SCT_STATUS_INVALID_SIGNATURE, &verify_result.scts);
+
+  mock_cert_verifier()->AddResultForCertAndHost(
+      https_server()->GetCertificate().get(), "mixed-scts.test", verify_result,
+      net::OK);
+
+  SetExtendedReportingEnabled(true);
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server()->GetURL("mixed-scts.test", "/"));
+  WaitForRequests(1);
+  EXPECT_EQ(1u, requests_seen());
+
+  auto report = GetLastSeenReport();
+  EXPECT_EQ(1, report.included_scts_size());
+}
+
+IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest, NoValidSCTsNoReport) {
+  // Set up a mocked CertVerifyResult with only invalid SCTs.
+  net::CertVerifyResult verify_result;
+  verify_result.verified_cert = https_server()->GetCertificate().get();
+  verify_result.is_issued_by_known_root = true;
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions1",
+      "signature1", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_INVALID_TIMESTAMP, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions2",
+      "signature2", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_INVALID_SIGNATURE, &verify_result.scts);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, "extensions3",
+      "signature3", base::Time::Now(),
+      std::string(kTestNonGoogleLogId1, sizeof(kTestNonGoogleLogId1)),
+      net::ct::SCT_STATUS_INVALID_SIGNATURE, &verify_result.scts);
+
+  mock_cert_verifier()->AddResultForCertAndHost(
+      https_server()->GetCertificate().get(), "invalid-scts.test",
+      verify_result, net::OK);
+
+  SetExtendedReportingEnabled(true);
+  ui_test_utils::NavigateToURL(
+      browser(), https_server()->GetURL("invalid-scts.test", "/"));
   EXPECT_EQ(0u, requests_seen());
   EXPECT_TRUE(FlushAndCheckZeroReports());
 }
 
-// TODO(crbug.com/1107975): Add test for "invalid SCTs should not get reported".
-// This is blocked on https://crrev.com/c/1188845 to allow us to use the
-// MockCertVerifier to mock CT results.
-
 class SCTReportingServiceZeroSamplingRateBrowserTest
     : public SCTReportingServiceBrowserTest {
  public:
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
index 5cffd03..759cef0 100644
--- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
+++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
@@ -18,18 +18,6 @@
 
 namespace sync_sessions {
 
-// static
-void SyncSessionsRouterTabHelper::CreateForWebContents(
-    content::WebContents* web_contents,
-    SyncSessionsWebContentsRouter* router) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new SyncSessionsRouterTabHelper(
-                                  web_contents, router)));
-  }
-}
-
 SyncSessionsRouterTabHelper::SyncSessionsRouterTabHelper(
     content::WebContents* web_contents,
     SyncSessionsWebContentsRouter* router)
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
index fe9716a..2bfb10e8 100644
--- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
+++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
@@ -34,10 +34,6 @@
  public:
   ~SyncSessionsRouterTabHelper() override;
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      SyncSessionsWebContentsRouter* session_router);
-
   // WebContentsObserver implementation.
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
index 945e400..728221f 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
@@ -66,7 +66,7 @@
 google_apis::CancelCallbackOnce DriveServiceOnWorker::DownloadFile(
     const base::FilePath& local_cache_path,
     const std::string& resource_id,
-    const google_apis::DownloadActionCallback& download_action_callback,
+    google_apis::DownloadActionCallback download_action_callback,
     const google_apis::GetContentCallback& get_content_callback,
     google_apis::ProgressCallback progress_callback) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -77,7 +77,7 @@
           &DriveServiceWrapper::DownloadFile, wrapper_, local_cache_path,
           resource_id,
           RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
-                                    download_action_callback),
+                                    std::move(download_action_callback)),
           RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
                                     get_content_callback),
           RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
@@ -315,7 +315,7 @@
   return google_apis::CancelCallbackOnce();
 }
 
-google_apis::CancelCallback DriveServiceOnWorker::Search(
+google_apis::CancelCallbackOnce DriveServiceOnWorker::Search(
     const std::string& search_query,
     google_apis::FileListCallback callback) {
   NOTREACHED();
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.h b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.h
index b79c94a..d1b9d18f6 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.h
+++ b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.h
@@ -52,7 +52,7 @@
   google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback) override;
 
@@ -120,7 +120,7 @@
   google_apis::CancelCallbackOnce GetAllFileList(
       const std::string& team_drive_id,
       google_apis::FileListCallback callback) override;
-  google_apis::CancelCallback Search(
+  google_apis::CancelCallbackOnce Search(
       const std::string& search_query,
       google_apis::FileListCallback callback) override;
   google_apis::CancelCallback TrashResource(
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.cc b/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.cc
index bc2de6a..d400e91 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.cc
@@ -39,15 +39,13 @@
 void DriveServiceWrapper::DownloadFile(
     const base::FilePath& local_cache_path,
     const std::string& resource_id,
-    const google_apis::DownloadActionCallback& download_action_callback,
+    google_apis::DownloadActionCallback download_action_callback,
     const google_apis::GetContentCallback& get_content_callback,
     google_apis::ProgressCallback progress_callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  drive_service_->DownloadFile(local_cache_path,
-                               resource_id,
-                               download_action_callback,
-                               get_content_callback,
-                               progress_callback);
+  drive_service_->DownloadFile(local_cache_path, resource_id,
+                               std::move(download_action_callback),
+                               get_content_callback, progress_callback);
 }
 
 void DriveServiceWrapper::GetAboutResource(
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.h b/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.h
index 7b2e2fa..e7c3a65 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.h
+++ b/chrome/browser/sync_file_system/drive_backend/drive_service_wrapper.h
@@ -37,7 +37,7 @@
   void DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback);
 
diff --git a/chrome/browser/ui/android/infobars/update_password_infobar.cc b/chrome/browser/ui/android/infobars/update_password_infobar.cc
index 11fc90b..f386820f 100644
--- a/chrome/browser/ui/android/infobars/update_password_infobar.cc
+++ b/chrome/browser/ui/android/infobars/update_password_infobar.cc
@@ -9,6 +9,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/android/chrome_jni_headers/UpdatePasswordInfoBar_jni.h"
 #include "chrome/browser/password_manager/android/update_password_infobar_delegate_android.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
@@ -18,8 +19,11 @@
 using base::android::JavaParamRef;
 
 UpdatePasswordInfoBar::UpdatePasswordInfoBar(
-    std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate)
-    : ChromeConfirmInfoBar(std::move(delegate)) {}
+    std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate,
+    base::Optional<AccountInfo> account_info)
+    : ChromeConfirmInfoBar(std::move(delegate)) {
+  account_info_ = account_info;
+}
 
 UpdatePasswordInfoBar::~UpdatePasswordInfoBar() {}
 
@@ -40,7 +44,10 @@
       ConvertUTF16ToJavaString(env, update_password_delegate->GetMessageText());
   ScopedJavaLocalRef<jstring> details_message_text = ConvertUTF16ToJavaString(
       env, update_password_delegate->GetDetailsMessageText());
-
+  ScopedJavaLocalRef<jobject> account_info =
+      account_info_.has_value()
+          ? ConvertToJavaAccountInfo(env, account_info_.value())
+          : nullptr;
   std::vector<base::string16> usernames;
   unsigned int selected_username =
       update_password_delegate->GetDisplayUsernames(&usernames);
@@ -50,7 +57,7 @@
   base::android::ScopedJavaLocalRef<jobject> infobar;
   infobar.Reset(Java_UpdatePasswordInfoBar_show(
       env, GetJavaIconId(), display_usernames, selected_username, message_text,
-      details_message_text, ok_button_text));
+      details_message_text, ok_button_text, account_info));
 
   java_infobar_.Reset(env, infobar.obj());
   return infobar;
diff --git a/chrome/browser/ui/android/infobars/update_password_infobar.h b/chrome/browser/ui/android/infobars/update_password_infobar.h
index 340720f..fb13af7 100644
--- a/chrome/browser/ui/android/infobars/update_password_infobar.h
+++ b/chrome/browser/ui/android/infobars/update_password_infobar.h
@@ -8,14 +8,15 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
+#include "components/signin/public/identity_manager/account_info.h"
 
 class UpdatePasswordInfoBarDelegate;
 
 // The infobar to be used with UpdatePasswordInfoBarDelegate.
 class UpdatePasswordInfoBar : public ChromeConfirmInfoBar {
  public:
-  explicit UpdatePasswordInfoBar(
-      std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate);
+  UpdatePasswordInfoBar(std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate,
+                        base::Optional<AccountInfo> account_info);
   ~UpdatePasswordInfoBar() override;
 
   int GetIdOfSelectedUsername() const;
@@ -29,6 +30,8 @@
 
   base::android::ScopedJavaGlobalRef<jobject> java_infobar_;
 
+  base::Optional<AccountInfo> account_info_;
+
   DISALLOW_COPY_AND_ASSIGN(UpdatePasswordInfoBar);
 };
 
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index d0e20a8..044c53c 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2232,6 +2232,9 @@
       <message name="IDS_PAGE_INFO_PREVIEW_LOAD_ORIGINAL" desc="This text, when clicked, loads the original page from its origin without any treatments. This text is shown in the page info bubble when the currently viewed page has been modified to be a lighter and faster version of the original page.">
         <ph name="BEGIN_LINK">&lt;link&gt;</ph>Load original page<ph name="END_LINK">&lt;/link&gt;</ph> from <ph name="DOMAIN_NAME">%1$s<ex>google.com</ex></ph>
       </message>
+      <message name="IDS_PAGE_INFO_CONNECTION_PAINT_PREVIEW" desc="Message to display in the page info bubble when viewing a preview of a page.">
+        You are viewing a preview of this page
+      </message>
 
       <!-- Sad tab page -->
       <message name="IDS_SAD_TAB_SUGGESTIONS" desc="The help message displayed on the sad tab page after a tab crashes.">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PAGE_INFO_CONNECTION_PAINT_PREVIEW.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PAGE_INFO_CONNECTION_PAINT_PREVIEW.png.sha1
new file mode 100644
index 0000000..d5102280
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PAGE_INFO_CONNECTION_PAINT_PREVIEW.png.sha1
@@ -0,0 +1 @@
+fb699bf73956180b5918a8efa4f015a208a7352a
\ No newline at end of file
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_browsertest.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_browsertest.cc
index 9425eef..d5b2fd5 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_browsertest.cc
@@ -15,6 +15,8 @@
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_test_util.h"
@@ -137,9 +139,7 @@
 
   ~AppServiceAppWindowBrowserTest() override = default;
 
-  void SetUp() override {
-    extensions::PlatformAppBrowserTest::SetUp();
-  }
+  void SetUp() override { extensions::PlatformAppBrowserTest::SetUp(); }
 
   void SetUpOnMainThread() override {
     controller_ = ChromeLauncherController::instance();
@@ -350,6 +350,54 @@
   EXPECT_EQ(0u, windows.size());
 }
 
+class AppServiceAppWindowBorealisBrowserTest
+    : public AppServiceAppWindowBrowserTest {
+ public:
+  ~AppServiceAppWindowBorealisBrowserTest() override = default;
+};
+
+IN_PROC_BROWSER_TEST_F(AppServiceAppWindowBorealisBrowserTest,
+                       BorealisKnownApp) {
+  // Generate a fake app.
+  vm_tools::apps::ApplicationList list;
+  list.set_vm_name("vm");
+  list.set_container_name("container");
+  list.set_vm_type(vm_tools::apps::ApplicationList_VmType_BOREALIS);
+  vm_tools::apps::App* app = list.add_apps();
+  app->set_desktop_file_id("foo.desktop");
+  app->mutable_name()->add_values()->set_value("foo");
+  app->set_no_display(false);
+  guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile())
+      ->UpdateApplicationList(list);
+  app_service_proxy_->FlushMojoCallsForTesting();
+
+  views::Widget* widget = CreateExoWindow("org.chromium.borealis.wmclass.foo");
+  std::string app_id = guest_os::GuestOsRegistryService::GenerateAppId(
+      "foo.desktop", "vm", "container");
+
+  EXPECT_EQ(1u,
+            app_service_proxy_->InstanceRegistry().GetWindows(app_id).size());
+  EXPECT_NE(-1, shelf_model()->ItemIndexByAppID(app_id));
+
+  widget->CloseNow();
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetWindows(app_id).empty());
+}
+
+IN_PROC_BROWSER_TEST_F(AppServiceAppWindowBorealisBrowserTest,
+                       BorealisUnknownApp) {
+  views::Widget* widget = CreateExoWindow("org.chromium.borealis.wmclass.bar");
+  std::string app_id = "crostini:org.chromium.termina.wmclass.bar";
+
+  EXPECT_EQ(1u,
+            app_service_proxy_->InstanceRegistry().GetWindows(app_id).size());
+  EXPECT_NE(-1, shelf_model()->ItemIndexByAppID(app_id));
+
+  widget->CloseNow();
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetWindows(app_id).empty());
+}
+
 class AppServiceAppWindowWebAppBrowserTest
     : public AppServiceAppWindowBrowserTest {
  protected:
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
index f5adb2b..fb0d62c 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
@@ -14,6 +14,8 @@
 #include "base/stl_util.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/borealis/borealis_service.h"
+#include "chrome/browser/chromeos/borealis/borealis_window_manager.h"
 #include "chrome/browser/chromeos/crosapi/browser_util.h"
 #include "chrome/browser/chromeos/crostini/crostini_features.h"
 #include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h"
@@ -599,8 +601,19 @@
   if (crosapi::browser_util::IsLacrosWindow(window))
     return ash::ShelfID(extension_misc::kLacrosAppId);
 
+  std::string shelf_app_id;
+  if (borealis::BorealisWindowManager::IsBorealisWindow(window)) {
+    for (auto* profile : profile_list_) {
+      shelf_app_id = borealis::BorealisService::GetForProfile(profile)
+                         ->WindowManager()
+                         .GetShelfAppId(window);
+      if (!shelf_app_id.empty()) {
+        return ash::ShelfID(shelf_app_id);
+      }
+    }
+  }
+
   if (crostini_tracker_) {
-    std::string shelf_app_id;
     shelf_app_id = crostini_tracker_->GetShelfAppId(window);
     if (!shelf_app_id.empty())
       return ash::ShelfID(shelf_app_id);
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 3cd19bd..72fd3d8d 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -521,7 +521,13 @@
 // verifying that we don't crash when we pass this limit.
 // Warning: this test can take >30 seconds when running on a slow (low
 // memory?) Mac builder.
-IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) {
+// Test is flaky on Win: https://crbug.com/1099186.
+#if defined(OS_WIN)
+#define MAYBE_ThirtyFourTabs DISABLED_ThirtyFourTabs
+#else
+#define MAYBE_ThirtyFourTabs ThirtyFourTabs
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) {
   GURL url(ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(kTitle2File)));
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 3eb2be7..75a43628 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -50,6 +50,7 @@
 #include "chromeos/login/login_state/login_state.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
+#include "components/signin/public/identity_manager/consent_level.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/common/constants.h"
@@ -479,7 +480,8 @@
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 void ShowBrowserSignin(Browser* browser,
-                       signin_metrics::AccessPoint access_point) {
+                       signin_metrics::AccessPoint access_point,
+                       signin::ConsentLevel consent_level) {
   Profile* original_profile = browser->profile()->GetOriginalProfile();
   DCHECK(original_profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed));
 
@@ -490,11 +492,21 @@
       std::make_unique<ScopedTabbedBrowserDisplayer>(original_profile);
   browser = displayer->browser();
 
-  profiles::BubbleViewMode bubble_view_mode =
-      IdentityManagerFactory::GetForProfile(original_profile)
-              ->HasPrimaryAccount()
-          ? profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH
-          : profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN;
+  profiles::BubbleViewMode bubble_view_mode;
+  if (IdentityManagerFactory::GetForProfile(original_profile)
+          ->HasPrimaryAccount()) {
+    bubble_view_mode = profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH;
+  } else {
+    switch (consent_level) {
+      case signin::ConsentLevel::kSync:
+        bubble_view_mode = profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN;
+        break;
+      case signin::ConsentLevel::kNotRequired:
+        bubble_view_mode = profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT;
+        break;
+    }
+  }
+
   browser->signin_view_controller()->ShowSignin(bubble_view_mode, access_point);
 }
 
@@ -506,7 +518,7 @@
           ->HasPrimaryAccount())
     ShowSettings(browser);
   else
-    ShowBrowserSignin(browser, access_point);
+    ShowBrowserSignin(browser, access_point, signin::ConsentLevel::kSync);
 }
 #endif
 
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index 18d32fb..9b04495 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -23,6 +23,10 @@
 #include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h"
 #endif
 
+namespace signin {
+enum class ConsentLevel;
+}  // namespace signin
+
 class Browser;
 class Profile;
 
@@ -162,7 +166,8 @@
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 // Initiates signin in a new browser tab.
 void ShowBrowserSignin(Browser* browser,
-                       signin_metrics::AccessPoint access_point);
+                       signin_metrics::AccessPoint access_point,
+                       signin::ConsentLevel consent_level);
 
 // If the user is already signed in, shows the "Signin" portion of Settings,
 // otherwise initiates signin in a new browser tab.
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble.cc b/chrome/browser/ui/views/accessibility/caption_bubble.cc
index 5a24adc..005f071c 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble.cc
@@ -339,6 +339,8 @@
       SkColorSetA(gfx::kGoogleGrey900, kCaptionBubbleAlpha);
   set_color(caption_bubble_color_);
   set_close_on_deactivate(false);
+  // The caption bubble starts out hidden and unable to be activated.
+  SetCanActivate(false);
 
   auto label = std::make_unique<views::Label>();
   label->SetMultiLine(true);
@@ -681,6 +683,9 @@
 void CaptionBubble::OnWidgetVisibilityChanged(views::Widget* widget,
                                               bool visible) {
   DCHECK_EQ(widget, GetWidget());
+  // The caption bubble can only be activated when it is visible. Nothing else,
+  // including the focus manager, can activate the caption bubble.
+  SetCanActivate(visible);
   // Ensure that the widget is only activated when it is visible.
   // TODO(crbug.com/1144201): Investigate whether Hide() should always
   // deactivate widgets, and if so, remove this.
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
index 5808e00..22bfb961 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -104,6 +104,10 @@
     return controller_ && controller_->IsWidgetVisibleForTesting();
   }
 
+  bool CanWidgetActivate() {
+    return GetCaptionWidget() && GetCaptionWidget()->CanActivate();
+  }
+
   bool IsWidgetActive() {
     return GetCaptionWidget() && GetCaptionWidget()->IsActive();
   }
@@ -1034,12 +1038,15 @@
 IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest,
                        BubbleDeactivatedWhenHidden) {
   EXPECT_FALSE(IsWidgetVisible());
+  EXPECT_FALSE(CanWidgetActivate());
   EXPECT_FALSE(IsWidgetActive());
   OnPartialTranscription("Cows can detect odors up to 6 miles away.");
   EXPECT_TRUE(IsWidgetVisible());
+  EXPECT_TRUE(CanWidgetActivate());
   EXPECT_TRUE(IsWidgetActive());
   ClickButton(GetCloseButton());
   EXPECT_FALSE(IsWidgetVisible());
+  EXPECT_FALSE(CanWidgetActivate());
   EXPECT_FALSE(IsWidgetActive());
 }
 #endif
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 fb94fb3..06693bc 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
@@ -31,6 +31,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/views/background.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 #include "ui/views/window/hit_test_utils.h"
 
 #if defined(OS_WIN)
@@ -400,3 +401,6 @@
   // into the view hierarchy.
   return frame_->GetThemeProvider();
 }
+
+BEGIN_METADATA(BrowserNonClientFrameView, views::NonClientFrameView)
+END_METADATA
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 3d692cb..1ee4609 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
+#include "ui/views/metadata/metadata_header_macros.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/non_client_view.h"
 
@@ -32,11 +33,15 @@
                                   public ProfileAttributesStorage::Observer,
                                   public TabStripObserver {
  public:
+  METADATA_HEADER(BrowserNonClientFrameView);
   // The minimum total height users should have to use as a drag handle to move
   // the window with.
   static constexpr int kMinimumDragHeight = 8;
 
   BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view);
+  BrowserNonClientFrameView(const BrowserNonClientFrameView&) = delete;
+  BrowserNonClientFrameView& operator=(const BrowserNonClientFrameView&) =
+      delete;
   ~BrowserNonClientFrameView() override;
 
   BrowserView* browser_view() const { return browser_view_; }
@@ -200,8 +205,6 @@
 
   base::ScopedObservation<TabStrip, TabStripObserver> tab_strip_observation_{
       this};
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameView);
 };
 
 namespace chrome {
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 dd770a3..fc96fa1b 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -42,6 +42,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/strings/grit/ui_strings.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 #include "ui/views/win/hwnd_util.h"
 #include "ui/views/window/client_view.h"
 
@@ -69,8 +70,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // GlassBrowserFrameView, public:
 
-constexpr char GlassBrowserFrameView::kClassName[];
-
 SkColor GlassBrowserFrameView::GetReadableFeatureColor(
     SkColor background_color) {
   // color_utils::GetColorWithMaxContrast()/IsDark() aren't used here because
@@ -391,10 +390,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // GlassBrowserFrameView, views::View overrides:
 
-const char* GlassBrowserFrameView::GetClassName() const {
-  return kClassName;
-}
-
 void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) {
   TRACE_EVENT0("views.frame", "GlassBrowserFrameView::OnPaint");
   if (ShouldCustomDrawSystemTitlebar())
@@ -818,3 +813,6 @@
     initialized = true;
   }
 }
+
+BEGIN_METADATA(GlassBrowserFrameView, BrowserNonClientFrameView)
+END_METADATA
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index 549a5fe..0757a72f 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/views/frame/windows_10_caption_button.h"
 #include "chrome/browser/ui/views/tab_icon_view.h"
 #include "chrome/browser/ui/views/tab_icon_view_model.h"
+#include "ui/views/metadata/metadata_header_macros.h"
 #include "ui/views/window/non_client_view.h"
 
 class BrowserView;
@@ -19,12 +20,11 @@
 class GlassBrowserFrameView : public BrowserNonClientFrameView,
                               public TabIconViewModel {
  public:
+  METADATA_HEADER(GlassBrowserFrameView);
   // Alpha to use for features in the titlebar (the window title and caption
   // buttons) when the window is inactive. They are opaque when active.
   static constexpr SkAlpha kInactiveTitlebarFeatureAlpha = 0x66;
 
-  static constexpr char kClassName[] = "GlassBrowserFrameView";
-
   static SkColor GetReadableFeatureColor(SkColor background_color);
 
   // Constructs a non-client view for an BrowserFrame.
@@ -74,7 +74,6 @@
 
  protected:
   // views::View:
-  const char* GetClassName() const override;
   void OnPaint(gfx::Canvas* canvas) override;
   void Layout() override;
 
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
index a412655..f825701a 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
@@ -15,6 +15,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
+#include "ui/views/view_utils.h"
 
 class WebAppGlassBrowserFrameViewTest : public InProcessBrowserTest {
  public:
@@ -55,7 +56,7 @@
     views::NonClientFrameView* frame_view =
         browser_view_->GetWidget()->non_client_view()->frame_view();
 
-    if (frame_view->GetClassName() != GlassBrowserFrameView::kClassName)
+    if (!views::IsViewClass<GlassBrowserFrameView>(frame_view))
       return false;
     glass_frame_view_ = static_cast<GlassBrowserFrameView*>(frame_view);
 
diff --git a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
index 9278216..61791e1 100644
--- a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
+++ b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
@@ -277,12 +277,13 @@
     base::string16 display_name = target.display_name;
     base::string16 secondary_display_name =
         target.secondary_display_name.value_or(base::string16());
+    base::Optional<gfx::ImageSkia> icon = target.icon;
 
     auto target_view = std::make_unique<SharesheetTargetButton>(
         base::BindRepeating(&SharesheetBubbleView::TargetButtonPressed,
                             base::Unretained(this),
                             base::Passed(std::move(target))),
-        display_name, secondary_display_name, target.icon,
+        display_name, secondary_display_name, icon,
         delegate_->GetVectorIcon(display_name));
 
     layout_for_target->AddView(std::move(target_view));
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
index 78b395d..914f0d3dea 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
@@ -13,15 +13,6 @@
 #include "ui/views/focus/focus_manager.h"
 #include "ui/views/widget/widget.h"
 
-// static
-void ChromeWebContentsViewFocusHelper::CreateForWebContents(
-    content::WebContents* web_contents) {
-  if (!ChromeWebContentsViewFocusHelper::FromWebContents(web_contents)) {
-    web_contents->SetUserData(
-        ChromeWebContentsViewFocusHelper::UserDataKey(),
-        base::WrapUnique(new ChromeWebContentsViewFocusHelper(web_contents)));
-  }
-}
 
 ChromeWebContentsViewFocusHelper::ChromeWebContentsViewFocusHelper(
     content::WebContents* web_contents)
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
index a0bc3e6..f629fea 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
@@ -24,11 +24,6 @@
 class ChromeWebContentsViewFocusHelper
     : public content::WebContentsUserData<ChromeWebContentsViewFocusHelper> {
  public:
-  // Creates a ChromeWebContentsViewFocusHelper for the given
-  // WebContents. If a ChromeWebContentsViewFocusHelper is already
-  // associated with the WebContents, this method is a no-op.
-  static void CreateForWebContents(content::WebContents* web_contents);
-
   void StoreFocus();
   bool RestoreFocus();
   void ResetStoredFocus();
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc
index a63fdc3..deabec9 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -166,9 +166,11 @@
 bool NewTabButton::GetHitTestMask(SkPath* mask) const {
   DCHECK(mask);
 
+  gfx::Point origin = GetContentsBounds().origin();
+  if (base::i18n::IsRTL())
+    origin.set_x(GetInsets().right());
   const float scale = GetWidget()->GetCompositor()->device_scale_factor();
-  // TODO(pkasting): Fitts' Law horizontally when appropriate.
-  SkPath border = GetBorderPath(GetContentsBounds().origin(), scale,
+  SkPath border = GetBorderPath(origin, scale,
                                 tab_strip_->controller()->IsFrameCondensed());
   mask->addPath(border, SkMatrix::Scale(1 / scale, 1 / scale));
   return true;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index b96aef2..61b1ec4 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -556,7 +556,7 @@
 #endif
   }
 
-  void ReleaseInputAfterWindowDetached() {
+  void ReleaseInputAfterWindowDetached(int first_dragged_tab_width) {
     // On macOS, we want to avoid generating the input event [which requires an
     // associated window] until the window has been detached. Failure to do so
     // causes odd behavior [e.g. on macOS 10.10, the mouse-up will reactivate
@@ -566,11 +566,16 @@
           FROM_HERE,
           base::BindOnce(&DetachToBrowserTabDragControllerTest::
                              ReleaseInputAfterWindowDetached,
-                         base::Unretained(this)),
+                         base::Unretained(this), first_dragged_tab_width),
           base::TimeDelta::FromMilliseconds(1));
       return;
     }
 
+    // The tab getting dragged into the new browser should have the same width
+    // as before it was dragged.
+    EXPECT_EQ(first_dragged_tab_width,
+              GetTabStripForBrowser(browser_list->get(1))->tab_at(0)->width());
+
     // Windows hangs if you use a sync mouse event here.
     ASSERT_TRUE(ReleaseInput(0, true));
   }
@@ -1556,10 +1561,11 @@
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
 
   // Move to the first tab and drag it enough so that it detaches.
+  int tab_0_width = tab_strip->tab_at(0)->width();
   DragTabAndNotify(tab_strip,
                    base::BindOnce(&DetachToBrowserTabDragControllerTest::
                                       ReleaseInputAfterWindowDetached,
-                                  base::Unretained(this)));
+                                  base::Unretained(this), tab_0_width));
 
   // Should no longer be dragging.
   ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
@@ -1622,10 +1628,11 @@
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
 
   // Move to the first tab and drag it enough so that it detaches.
+  int tab_0_width = tab_strip->tab_at(0)->width();
   DragTabAndNotify(tab_strip,
                    base::BindOnce(&DetachToBrowserTabDragControllerTest::
                                       ReleaseInputAfterWindowDetached,
-                                  base::Unretained(this)));
+                                  base::Unretained(this), tab_0_width));
 
   // Should no longer be dragging.
   ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
@@ -1672,10 +1679,11 @@
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
 
   // Move to the first tab and drag it enough so that it detaches.
+  int tab_0_width = tab_strip->tab_at(0)->width();
   DragTabAndNotify(tab_strip,
                    base::BindOnce(&DetachToBrowserTabDragControllerTest::
                                       ReleaseInputAfterWindowDetached,
-                                  base::Unretained(this)));
+                                  base::Unretained(this), tab_0_width));
 
   // Should no longer be dragging.
   ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
@@ -1729,10 +1737,11 @@
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
 
   // Move to the first tab and drag it enough so that it detaches.
+  int tab_0_width = tab_strip->tab_at(0)->width();
   DragTabAndNotify(tab_strip,
                    base::BindOnce(&DetachToBrowserTabDragControllerTest::
                                       ReleaseInputAfterWindowDetached,
-                                  base::Unretained(this)));
+                                  base::Unretained(this), tab_0_width));
 
   // Should no longer be dragging.
   ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
@@ -3417,11 +3426,12 @@
   AddTabsAndResetBrowser(browser(), 1, GetAppUrl());
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
 
-  // Drag tab to create a new browser.
+  // Move to the first tab and drag it enough so that it detaches.
+  int tab_0_width = tab_strip->tab_at(0)->width();
   DragTabAndNotify(tab_strip,
                    base::BindOnce(&DetachToBrowserTabDragControllerTest::
                                       ReleaseInputAfterWindowDetached,
-                                  base::Unretained(this)));
+                                  base::Unretained(this), tab_0_width));
 
   // New browser should be TYPE_APP.
   ASSERT_EQ(2u, browser_list->size());
diff --git a/chrome/browser/ui/webui/app_launcher_login_handler.cc b/chrome/browser/ui/webui/app_launcher_login_handler.cc
index 8bd55aeb..6d74f92 100644
--- a/chrome/browser/ui/webui/app_launcher_login_handler.cc
+++ b/chrome/browser/ui/webui/app_launcher_login_handler.cc
@@ -32,6 +32,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/identity_manager/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -126,7 +127,7 @@
       web_contents->GetURL().spec() == chrome::kChromeUIAppsURL
           ? signin_metrics::AccessPoint::ACCESS_POINT_APPS_PAGE_LINK
           : signin_metrics::AccessPoint::ACCESS_POINT_NTP_LINK;
-  chrome::ShowBrowserSignin(browser, access_point);
+  chrome::ShowBrowserSignin(browser, access_point, signin::ConsentLevel::kSync);
   RecordInHistogram(NTP_SIGN_IN_PROMO_CLICKED);
 }
 #endif
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
index dc53918a..15152e7 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/nearby_sharing/text_attachment.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/nearby_share/shared_resources.h"
+#include "chrome/browser/ui/webui/plural_string_handler.h"
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
@@ -66,6 +67,12 @@
       "close", base::BindRepeating(&NearbyShareDialogUI::HandleClose,
                                    base::Unretained(this)));
 
+  auto plural_string_handler = std::make_unique<PluralStringHandler>();
+  plural_string_handler->AddLocalizedString(
+      "nearbyShareContactVisibilityNumUnreachable",
+      IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE);
+  web_ui->AddMessageHandler(std::move(plural_string_handler));
+
   content::WebUIDataSource::Add(profile, html_source);
 
   const GURL& url = web_ui->GetWebContents()->GetVisibleURL();
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index 2960060..5705086 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/buildflags.h"
 #include "chrome/browser/media/kaleidoscope/constants.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h"
+#include "chrome/browser/media/kaleidoscope/kaleidoscope_identity_manager_impl.h"
 #include "chrome/browser/media/kaleidoscope/kaleidoscope_ui.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_service.h"
@@ -388,6 +389,14 @@
 }
 
 void NewTabPageUI::BindInterface(
+    mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager>
+        pending_page_handler) {
+  kaleidoscope_identity_manager_ =
+      std::make_unique<KaleidoscopeIdentityManagerImpl>(
+          std::move(pending_page_handler), profile_);
+}
+
+void NewTabPageUI::BindInterface(
     mojo::PendingReceiver<task_module::mojom::TaskModuleHandler>
         pending_receiver) {
   task_module_handler_ = std::make_unique<TaskModuleHandler>(
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
index 4aecfe2..cbae3251 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
@@ -34,6 +34,7 @@
 class GURL;
 class InstantService;
 class KaleidoscopeDataProviderImpl;
+class KaleidoscopeIdentityManagerImpl;
 class NewTabPageHandler;
 class Profile;
 class PromoBrowserCommandHandler;
@@ -79,6 +80,13 @@
           pending_receiver);
 
   // Instantiates the implementor of the
+  // media::mojom::KaleidoscopeIdentityManager mojo interface passing the
+  // pending receiver that will be internally bound.
+  void BindInterface(
+      mojo::PendingReceiver<media::mojom::KaleidoscopeIdentityManager>
+          pending_receiver);
+
+  // Instantiates the implementor of the
   // shopping_tasks::mojom::ShoppingTasksHandler mojo interface passing the
   // pending receiver that will be internally bound.
   void BindInterface(
@@ -138,6 +146,8 @@
 
   // Mojo implementations for modules:
   std::unique_ptr<KaleidoscopeDataProviderImpl> kaleidoscope_data_provider_;
+  std::unique_ptr<KaleidoscopeIdentityManagerImpl>
+      kaleidoscope_identity_manager_;
   std::unique_ptr<TaskModuleHandler> task_module_handler_;
 
   WEB_UI_CONTROLLER_TYPE_DECL();
diff --git a/chrome/browser/ui/webui/settings/OWNERS b/chrome/browser/ui/webui/settings/OWNERS
index 6686542..cca8351c 100644
--- a/chrome/browser/ui/webui/settings/OWNERS
+++ b/chrome/browser/ui/webui/settings/OWNERS
@@ -8,3 +8,4 @@
 per-file safe_browsing_handler*=msramek@chromium.org
 per-file safe_browsing_handler*=sauski@google.com
 per-file safety_check_handler*=andzaytsev@google.com
+per-file settings_security_key_handler*=file://device/fido/OWNERS
diff --git a/chrome/browser/ui/webui/settings/chromeos/main_section.cc b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
index cd5997e..c704bfc0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/main_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/metrics_handler.h"
+#include "chrome/browser/ui/webui/plural_string_handler.h"
 #include "chrome/browser/ui/webui/policy_indicator_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/browser_lifetime_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h"
@@ -186,6 +187,8 @@
 
   web_ui->AddMessageHandler(
       std::make_unique<::settings::BrowserLifetimeHandler>());
+
+  web_ui->AddMessageHandler(CreatePluralStringHandler());
 }
 
 int MainSection::GetSectionNameMessageId() const {
@@ -239,5 +242,20 @@
                                  base::ASCIIToUTF16(primary_user_email)));
 }
 
+std::unique_ptr<PluralStringHandler> MainSection::CreatePluralStringHandler() {
+  auto plural_string_handler = std::make_unique<PluralStringHandler>();
+  if (chromeos::features::IsAccountManagementFlowsV2Enabled()) {
+    plural_string_handler->AddLocalizedString("profileLabel",
+                                              IDS_OS_SETTINGS_PROFILE_LABEL_V2);
+  } else {
+    plural_string_handler->AddLocalizedString("profileLabel",
+                                              IDS_OS_SETTINGS_PROFILE_LABEL);
+  }
+  plural_string_handler->AddLocalizedString(
+      "nearbyShareContactVisibilityNumUnreachable",
+      IDS_NEARBY_CONTACT_VISIBILITY_NUM_UNREACHABLE);
+  return plural_string_handler;
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/main_section.h b/chrome/browser/ui/webui/settings/chromeos/main_section.h
index 569b482..3260534 100644
--- a/chrome/browser/ui/webui/settings/chromeos/main_section.h
+++ b/chrome/browser/ui/webui/settings/chromeos/main_section.h
@@ -8,6 +8,8 @@
 #include "base/values.h"
 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h"
 
+class PluralStringHandler;
+
 namespace content {
 class WebUIDataSource;
 }  // namespace content
@@ -35,6 +37,7 @@
   void RegisterHierarchy(HierarchyGenerator* generator) const override;
 
   void AddChromeOSUserStrings(content::WebUIDataSource* html_source);
+  std::unique_ptr<PluralStringHandler> CreatePluralStringHandler();
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/people_section.cc b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
index 15aa50a6..45789c43 100644
--- a/chrome/browser/ui/webui/settings/chromeos/people_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h"
-#include "chrome/browser/ui/webui/plural_string_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h"
@@ -849,16 +848,6 @@
   web_ui->AddMessageHandler(
       std::make_unique<::settings::ProfileInfoHandler>(profile()));
 
-  auto plural_string_handler = std::make_unique<PluralStringHandler>();
-  if (chromeos::features::IsAccountManagementFlowsV2Enabled()) {
-    plural_string_handler->AddLocalizedString("profileLabel",
-                                              IDS_OS_SETTINGS_PROFILE_LABEL_V2);
-  } else {
-    plural_string_handler->AddLocalizedString("profileLabel",
-                                              IDS_OS_SETTINGS_PROFILE_LABEL);
-  }
-  web_ui->AddMessageHandler(std::move(plural_string_handler));
-
   if (account_manager_) {
     web_ui->AddMessageHandler(
         std::make_unique<chromeos::settings::AccountManagerUIHandler>(
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
index a28d224..f8df63f8 100644
--- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/browser/ui/webui/signin/signin_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/signin/public/identity_manager/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
@@ -448,7 +449,7 @@
 
   signin_metrics::AccessPoint access_point =
       signin_metrics::AccessPoint::ACCESS_POINT_MENU;
-  chrome::ShowBrowserSignin(browser, access_point);
+  chrome::ShowBrowserSignin(browser, access_point, signin::ConsentLevel::kSync);
   content::WebContents* active_contents =
       browser->tab_strip_model()->GetActiveWebContents();
   DCHECK(active_contents);
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_linux.cc b/chrome/browser/web_applications/components/web_app_shortcut_linux.cc
index 84fb3e7f..1d9ae91 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_linux.cc
+++ b/chrome/browser/web_applications/components/web_app_shortcut_linux.cc
@@ -15,6 +15,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/nix/xdg_util.h"
+#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/kill.h"
@@ -40,6 +41,12 @@
 constexpr const char* kCreateShortcutIconResult =
     "Apps.CreateShortcutIcon.Linux.Result";
 
+// Testing hook for shell_integration_linux
+web_app::LaunchXdgUtilityForTesting& GetInstalledLaunchXdgUtilityForTesting() {
+  static base::NoDestructor<web_app::LaunchXdgUtilityForTesting> instance;
+  return *instance;
+}
+
 // Result of creating app shortcut icon.
 // Success is recorded for each icon image, but the first two errors
 // are per app, so the success/error ratio might not be very meaningful.
@@ -81,6 +88,14 @@
   UMA_HISTOGRAM_ENUMERATION(kCreateShortcutResult, result);
 }
 
+bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
+  if (GetInstalledLaunchXdgUtilityForTesting())
+    return std::move(GetInstalledLaunchXdgUtilityForTesting())
+        .Run(argv, exit_code);
+
+  return shell_integration_linux::LaunchXdgUtility(argv, exit_code);
+}
+
 const char kDirectoryFilename[] = "chrome-apps.directory";
 
 std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images,
@@ -132,8 +147,7 @@
     argv.push_back(temp_file_path.value());
     argv.push_back(icon_name);
     int exit_code;
-    if (!shell_integration_linux::LaunchXdgUtility(argv, &exit_code) ||
-        exit_code) {
+    if (!LaunchXdgUtility(argv, &exit_code) || exit_code) {
       LOG(WARNING) << "Could not install icon " << icon_name << ".png at size "
                    << width << ".";
       RecordCreateIcon(CreateShortcutIconResult::kFailToInstallIcon);
@@ -193,7 +207,8 @@
 // applications menu. If |directory_filename| is non-empty, creates a sub-menu
 // with |directory_filename| and |directory_contents|, and stores the shortcut
 // under the sub-menu.
-bool CreateShortcutInApplicationsMenu(const base::FilePath& shortcut_filename,
+bool CreateShortcutInApplicationsMenu(base::Environment* env,
+                                      const base::FilePath& shortcut_filename,
                                       const std::string& contents,
                                       const base::FilePath& directory_filename,
                                       const std::string& directory_contents) {
@@ -233,7 +248,7 @@
     argv.push_back(temp_directory_path.value());
   argv.push_back(temp_file_path.value());
   int exit_code;
-  shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
+  LaunchXdgUtility(argv, &exit_code);
 
   if (exit_code != 0) {
     RecordCreateShortcut(CreateShortcutResult::kFailToInstallShortcut);
@@ -245,10 +260,8 @@
   // manually run update-desktop-database on the user applications folder.
   // See this bug on xdg desktop-file-utils
   // https://gitlab.freedesktop.org/xdg/desktop-file-utils/issues/54
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
   base::FilePath user_applications_dir =
-      shell_integration_linux::GetDataWriteLocation(env.get()).Append(
-          "applications");
+      shell_integration_linux::GetDataWriteLocation(env).Append("applications");
   argv.clear();
   argv.push_back("update-desktop-database");
   argv.push_back(user_applications_dir.value());
@@ -258,7 +271,7 @@
   // completes). Failure means the file type associations for this desktop entry
   // may not show up in some file managers, but this is non-critical.
   int ignored_exit_code = 0;
-  shell_integration_linux::LaunchXdgUtility(argv, &ignored_exit_code);
+  LaunchXdgUtility(argv, &ignored_exit_code);
 
   return true;
 }
@@ -267,6 +280,12 @@
 
 namespace web_app {
 
+void SetLaunchXdgUtilityForTesting(
+    LaunchXdgUtilityForTesting launchXdgUtilityForTesting) {
+  GetInstalledLaunchXdgUtilityForTesting() =
+      std::move(launchXdgUtilityForTesting);
+}
+
 base::FilePath GetAppShortcutFilename(const base::FilePath& profile_path,
                                       const std::string& app_id) {
   DCHECK(!app_id.empty());
@@ -309,10 +328,11 @@
     argv.push_back(directory_filename.value());
   argv.push_back(shortcut_filename.value());
   int exit_code;
-  return shell_integration_linux::LaunchXdgUtility(argv, &exit_code);
+  return LaunchXdgUtility(argv, &exit_code);
 }
 
-bool CreateDesktopShortcut(const ShortcutInfo& shortcut_info,
+bool CreateDesktopShortcut(base::Environment* env,
+                           const ShortcutInfo& shortcut_info,
                            const ShortcutLocations& creation_locations) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
@@ -393,7 +413,7 @@
       base::JoinString(mime_types, ";"),
       creation_locations.applications_menu_location ==
           APP_MENU_LOCATION_HIDDEN);
-  success = CreateShortcutInApplicationsMenu(shortcut_filename, contents,
+  success = CreateShortcutInApplicationsMenu(env, shortcut_filename, contents,
                                              directory_filename,
                                              directory_contents) &&
             success;
@@ -407,18 +427,6 @@
     base::Environment* env,
     const base::FilePath& profile_path,
     const std::string& extension_id) {
-  base::FilePath desktop_path;
-  // If Get returns false, just leave desktop_path empty.
-  base::PathService::Get(base::DIR_USER_DESKTOP, &desktop_path);
-  return GetExistingShortcutLocations(env, profile_path, extension_id,
-                                      desktop_path);
-}
-
-ShortcutLocations GetExistingShortcutLocations(
-    base::Environment* env,
-    const base::FilePath& profile_path,
-    const std::string& extension_id,
-    const base::FilePath& desktop_path) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
@@ -428,6 +436,9 @@
   ShortcutLocations locations;
 
   // Determine whether there is a shortcut on desktop.
+  base::FilePath desktop_path;
+  // If Get returns false, just leave desktop_path empty.
+  base::PathService::Get(base::DIR_USER_DESKTOP, &desktop_path);
   if (!desktop_path.empty()) {
     locations.on_desktop =
         base::PathExists(desktop_path.Append(shortcut_filename));
@@ -469,11 +480,11 @@
   return (deleted_from_desktop && deleted_from_application_menu);
 }
 
-bool DeleteAllDesktopShortcuts(const base::FilePath& profile_path) {
+bool DeleteAllDesktopShortcuts(base::Environment* env,
+                               const base::FilePath& profile_path) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
   bool result = true;
   // Delete shortcuts from Desktop.
   base::FilePath desktop_path;
@@ -489,7 +500,7 @@
 
   // Delete shortcuts from |kDirectoryFilename|.
   base::FilePath applications_menu =
-      shell_integration_linux::GetDataWriteLocation(env.get());
+      shell_integration_linux::GetDataWriteLocation(env);
   applications_menu = applications_menu.AppendASCII("applications");
   std::vector<base::FilePath> shortcut_filenames_app_menu =
       shell_integration_linux::GetExistingProfileShortcutFilenames(
@@ -503,16 +514,35 @@
   return result;
 }
 
+void UpdateDesktopShortcuts(base::Environment* env,
+                            const ShortcutInfo& shortcut_info) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+
+  // Find out whether shortcuts are already installed.
+  ShortcutLocations creation_locations = GetExistingShortcutLocations(
+      env, shortcut_info.profile_path, shortcut_info.extension_id);
+
+  // Always create a hidden shortcut in applications if a visible one is not
+  // being created. This allows the operating system to identify the app, but
+  // not show it in the menu.
+  if (creation_locations.applications_menu_location == APP_MENU_LOCATION_NONE)
+    creation_locations.applications_menu_location = APP_MENU_LOCATION_HIDDEN;
+
+  CreateDesktopShortcut(env, shortcut_info, creation_locations);
+}
+
 namespace internals {
 
-bool CreatePlatformShortcuts(const base::FilePath& web_app_path,
+bool CreatePlatformShortcuts(const base::FilePath& /*web_app_path*/,
                              const ShortcutLocations& creation_locations,
                              ShortcutCreationReason /*creation_reason*/,
                              const ShortcutInfo& shortcut_info) {
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
-  return CreateDesktopShortcut(shortcut_info, creation_locations);
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  return CreateDesktopShortcut(env.get(), shortcut_info, creation_locations);
 #else
   return false;
 #endif
@@ -527,31 +557,19 @@
   return true;
 }
 
-void UpdatePlatformShortcuts(const base::FilePath& web_app_path,
+void UpdatePlatformShortcuts(const base::FilePath& /*web_app_path*/,
                              const base::string16& /*old_app_title*/,
                              const ShortcutInfo& shortcut_info) {
-  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
-                                                base::BlockingType::MAY_BLOCK);
-
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<base::Environment> env(base::Environment::Create());
-
-  // Find out whether shortcuts are already installed.
-  ShortcutLocations creation_locations = GetExistingShortcutLocations(
-      env.get(), shortcut_info.profile_path, shortcut_info.extension_id);
-
-  // Always create a hidden shortcut in applications if a visible one is not
-  // being created. This allows the operating system to identify the app, but
-  // not show it in the menu.
-  if (creation_locations.applications_menu_location == APP_MENU_LOCATION_NONE)
-    creation_locations.applications_menu_location = APP_MENU_LOCATION_HIDDEN;
-
-  CreatePlatformShortcuts(web_app_path, creation_locations,
-                          SHORTCUT_CREATION_AUTOMATED, shortcut_info);
+  UpdateDesktopShortcuts(env.get(), shortcut_info);
+#endif
 }
 
 void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-  DeleteAllDesktopShortcuts(profile_path);
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  DeleteAllDesktopShortcuts(env.get(), profile_path);
 #endif
 }
 
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_linux.h b/chrome/browser/web_applications/components/web_app_shortcut_linux.h
index c6e5844..161f375 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_linux.h
+++ b/chrome/browser/web_applications/components/web_app_shortcut_linux.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "base/callback.h"
+
 namespace base {
 class FilePath;
 class Environment;
@@ -17,11 +19,19 @@
 struct ShortcutInfo;
 struct ShortcutLocations;
 
+using LaunchXdgUtilityForTesting =
+    base::RepeatingCallback<bool(const std::vector<std::string>&, int*)>;
+
+// Test helper that hooking calls to shell_integration_linux::LaunchXdgUtility
+void SetLaunchXdgUtilityForTesting(
+    LaunchXdgUtilityForTesting launchXdgUtilityForTesting);
+
 // Create shortcuts on the desktop or in the application menu (as specified by
 // |shortcut_info|), for the web page or extension in |shortcut_info|.
 // For extensions, duplicate shortcuts are avoided, so if a requested shortcut
 // already exists it is deleted first.
-bool CreateDesktopShortcut(const ShortcutInfo& shortcut_info,
+bool CreateDesktopShortcut(base::Environment* env,
+                           const ShortcutInfo& shortcut_info,
                            const ShortcutLocations& creation_locations);
 
 // Returns filename for .desktop file based on |profile_path| and
@@ -39,14 +49,8 @@
     const base::FilePath& profile_path,
     const std::string& extension_id);
 
-// Version of GetExistingShortcutLocations which takes an explicit path
-// to the user's desktop directory. Useful for testing.
-// If |desktop_path| is empty, the desktop is not searched.
-ShortcutLocations GetExistingShortcutLocations(
-    base::Environment* env,
-    const base::FilePath& profile_path,
-    const std::string& extension_id,
-    const base::FilePath& desktop_path);
+void UpdateDesktopShortcuts(base::Environment* env,
+                            const ShortcutInfo& shortcut_info);
 
 // Delete any desktop shortcuts on desktop or in the application menu that have
 // been added for the extension with |extension_id| in |profile_path|. Returns
@@ -56,7 +60,8 @@
 
 // Delete any desktop shortcuts on desktop or in the application menu that have
 // for the profile in |profile_path|. Returns true on successful deletion.
-bool DeleteAllDesktopShortcuts(const base::FilePath& profile_path);
+bool DeleteAllDesktopShortcuts(base::Environment* env,
+                               const base::FilePath& profile_path);
 
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_linux_unittest.cc b/chrome/browser/web_applications/components/web_app_shortcut_linux_unittest.cc
index b8d062c..253aa9a 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_linux_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_shortcut_linux_unittest.cc
@@ -17,12 +17,17 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
 #include "base/test/scoped_path_override.h"
+#include "chrome/browser/shell_integration_linux.h"
 #include "chrome/browser/web_applications/components/web_app_id.h"
 #include "chrome/browser/web_applications/components/web_app_shortcut.h"
+#include "chrome/browser/web_applications/components/web_application_info.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -35,7 +40,7 @@
 // Provides mock environment variables values based on a stored map.
 class MockEnvironment : public base::Environment {
  public:
-  MockEnvironment() {}
+  MockEnvironment() = default;
   MockEnvironment(const MockEnvironment&) = delete;
   MockEnvironment& operator=(const MockEnvironment&) = delete;
 
@@ -68,113 +73,513 @@
 
 };
 
+class ScopedDesktopPath {
+ public:
+  ScopedDesktopPath() { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+  ScopedDesktopPath(const ScopedDesktopPath&) = delete;
+  ScopedDesktopPath& operator=(const ScopedDesktopPath&) = delete;
+
+  base::FilePath GetPath() {
+    base::FilePath desktop_path = temp_dir_.GetPath();
+    EXPECT_TRUE(base::CreateDirectory(desktop_path));
+    return desktop_path;
+  }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+};
+
+class ScopedApplicationsPath {
+ public:
+  ScopedApplicationsPath() { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+  ScopedApplicationsPath(const ScopedApplicationsPath&) = delete;
+  ScopedApplicationsPath& operator=(const ScopedApplicationsPath&) = delete;
+
+  base::FilePath GetPath() {
+    base::FilePath applications_path = temp_dir_.GetPath();
+    applications_path = applications_path.AppendASCII("applications");
+    EXPECT_TRUE(base::CreateDirectory(applications_path));
+    return applications_path;
+  }
+
+  base::FilePath GetDataHomePath() { return temp_dir_.GetPath(); }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+};
+
 }  // namespace
 
-TEST(ShellIntegrationTest, GetExistingShortcutLocations) {
-  base::FilePath kProfilePath("Profile 1");
-  const char kExtensionId[] = "test_extension";
-  const char kTemplateFilename[] = "chrome-test_extension-Profile_1.desktop";
-  base::FilePath kTemplateFilepath(kTemplateFilename);
-  const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true";
+class WebAppShortcutLinuxTest : public WebAppTest {
+ public:
+  base::FilePath CreateShortcutInPath(const base::FilePath& path) {
+    EXPECT_TRUE(base::PathExists(path));
+    base::FilePath shortcut_path = path.Append(GetTemplateFilename());
+    EXPECT_TRUE(base::WriteFile(shortcut_path, ""));
+    return shortcut_path;
+  }
 
-  content::BrowserTaskEnvironment task_environment;
+  std::unique_ptr<ShortcutInfo> GetShortcutInfo() {
+    auto shortcut_info = std::make_unique<ShortcutInfo>();
+    shortcut_info->extension_id = GetAppId();
+    shortcut_info->title = base::UTF8ToUTF16("app");
+    shortcut_info->profile_path =
+        base::FilePath("/a/b/c").Append(GetProfilePath());
+    gfx::ImageFamily image_family;
+    SquareSizePx icon_size_in_px = GetDesiredIconSizesForShortcut().back();
+    gfx::ImageSkia image_skia = CreateDefaultApplicationIcon(icon_size_in_px);
+    image_family.Add(gfx::Image(image_skia));
+    shortcut_info->favicon = std::move(image_family);
+    return shortcut_info;
+  }
+
+  std::string GetAppId() { return std::string("test_extension"); }
+
+  std::string GetTemplateFilename() {
+    return std::string("chrome-test_extension-Profile_1.desktop");
+  }
+
+  base::FilePath GetProfilePath() { return base::FilePath("Profile 1"); }
+
+  void ValidateDeleteApplicationsLaunchXdgUtility(
+      const std::vector<std::string>& argv,
+      int* exit_code) {
+    EXPECT_TRUE(exit_code);
+    *exit_code = 0;
+
+    std::vector<std::string> expected_argv;
+    expected_argv.push_back("xdg-desktop-menu");
+    expected_argv.push_back("uninstall");
+    expected_argv.push_back("--mode");
+    expected_argv.push_back("user");
+    expected_argv.push_back("chrome-apps.directory");
+    expected_argv.push_back(GetTemplateFilename());
+
+    EXPECT_EQ(argv, expected_argv);
+  }
+
+  void ValidateCreateDesktopShortcutLaunchXdgUtility(
+      const std::vector<std::string>& argv,
+      int* exit_code,
+      const base::FilePath& expected_applications_path,
+      int invoke_count) {
+    EXPECT_TRUE(exit_code);
+    *exit_code = 0;
+
+    // There are 4 calls to this function:
+    //  case 0) delete the existing shortcut
+    //  case 1) install the icon for the new shortcut
+    //  case 2) install the new shortcut
+    //  case 3) update desktop database
+    EXPECT_LE(invoke_count, 4);
+
+    std::vector<std::string> expected_argv;
+    switch (invoke_count) {
+      case 0:
+        expected_argv.push_back("xdg-desktop-menu");
+        expected_argv.push_back("uninstall");
+        expected_argv.push_back("--mode");
+        expected_argv.push_back("user");
+        expected_argv.push_back(GetTemplateFilename());
+        break;
+
+      case 1:
+        // The icon is generated to a temporary path, but the file name
+        // should be known Confirm the file name is what we expect, and use
+        // the parameter passed in.
+        EXPECT_EQ(argv.size(), 8u);
+        EXPECT_TRUE(argv[6].find("chrome-test_extension-Profile_1.png") !=
+                    std::string::npos);
+        expected_argv.push_back("xdg-icon-resource");
+        expected_argv.push_back("install");
+        expected_argv.push_back("--mode");
+        expected_argv.push_back("user");
+        expected_argv.push_back("--size");
+        expected_argv.push_back("512");
+        expected_argv.push_back(argv[6]);
+        expected_argv.push_back("chrome-test_extension-Profile_1");
+        break;
+
+      case 2:
+        // The desktop file is generated to a temporary path, but the file
+        // name should be known Confirm the file name is what we expect, and
+        // use the parameter passed in.
+        EXPECT_EQ(argv.size(), 6u);
+        EXPECT_TRUE(argv[4].find("chrome-apps.directory") != std::string::npos);
+        EXPECT_TRUE(argv[5].find(GetTemplateFilename()) != std::string::npos);
+
+        expected_argv.push_back("xdg-desktop-menu");
+        expected_argv.push_back("install");
+        expected_argv.push_back("--mode");
+        expected_argv.push_back("user");
+        expected_argv.push_back(argv[4]);
+        expected_argv.push_back(argv[5]);
+        break;
+
+      case 3:
+        expected_argv.push_back("update-desktop-database");
+        expected_argv.push_back(expected_applications_path.value());
+        break;
+    }
+
+    EXPECT_EQ(expected_argv, argv);
+  }
+};
+
+TEST_F(WebAppShortcutLinuxTest, GetExistingShortcutLocations) {
+  base::FilePath kTemplateFilepath(GetTemplateFilename());
 
   // No existing shortcuts.
   {
     MockEnvironment env;
     ShortcutLocations result =
-        GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
+        GetExistingShortcutLocations(&env, GetProfilePath(), GetAppId());
     EXPECT_FALSE(result.on_desktop);
     EXPECT_EQ(APP_MENU_LOCATION_NONE, result.applications_menu_location);
-
     EXPECT_FALSE(result.in_quick_launch_bar);
+    EXPECT_FALSE(result.in_startup);
   }
 
   // Shortcut on desktop.
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    base::FilePath desktop_path = temp_dir.GetPath();
-
+    ScopedDesktopPath scoped_desktop_path;
+    base::ScopedPathOverride user_desktop_override(
+        base::DIR_USER_DESKTOP, scoped_desktop_path.GetPath());
     MockEnvironment env;
-    ASSERT_TRUE(base::CreateDirectory(desktop_path));
-    ASSERT_TRUE(base::WriteFile(desktop_path.Append(kTemplateFilename), ""));
-    ShortcutLocations result = GetExistingShortcutLocations(
-        &env, kProfilePath, kExtensionId, desktop_path);
+
+    CreateShortcutInPath(scoped_desktop_path.GetPath());
+    ShortcutLocations result =
+        GetExistingShortcutLocations(&env, GetProfilePath(), GetAppId());
     EXPECT_TRUE(result.on_desktop);
     EXPECT_EQ(APP_MENU_LOCATION_NONE, result.applications_menu_location);
-
     EXPECT_FALSE(result.in_quick_launch_bar);
+    EXPECT_FALSE(result.in_startup);
   }
 
   // Shortcut in applications directory.
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    base::FilePath apps_path = temp_dir.GetPath().Append("applications");
-
+    ScopedApplicationsPath scoped_applications_path;
     MockEnvironment env;
-    env.Set("XDG_DATA_HOME", temp_dir.GetPath().value());
-    ASSERT_TRUE(base::CreateDirectory(apps_path));
-    ASSERT_TRUE(base::WriteFile(apps_path.Append(kTemplateFilename), ""));
+
+    env.Set("XDG_DATA_HOME",
+            scoped_applications_path.GetDataHomePath().value());
+    CreateShortcutInPath(scoped_applications_path.GetPath());
     ShortcutLocations result =
-        GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
+        GetExistingShortcutLocations(&env, GetProfilePath(), GetAppId());
     EXPECT_FALSE(result.on_desktop);
     EXPECT_EQ(APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
               result.applications_menu_location);
-
     EXPECT_FALSE(result.in_quick_launch_bar);
+    EXPECT_FALSE(result.in_startup);
   }
 
   // Shortcut in applications directory with NoDisplay=true.
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    base::FilePath apps_path = temp_dir.GetPath().Append("applications");
-
+    ScopedApplicationsPath scoped_applications_path;
     MockEnvironment env;
-    env.Set("XDG_DATA_HOME", temp_dir.GetPath().value());
-    ASSERT_TRUE(base::CreateDirectory(apps_path));
-    ASSERT_TRUE(base::WriteFile(apps_path.Append(kTemplateFilename),
-                                kNoDisplayDesktopFile));
+
+    env.Set("XDG_DATA_HOME",
+            scoped_applications_path.GetDataHomePath().value());
+    ASSERT_TRUE(base::WriteFile(
+        scoped_applications_path.GetPath().Append(GetTemplateFilename()),
+        "[Desktop Entry]\nNoDisplay=true"));
     ShortcutLocations result =
-        GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
+        GetExistingShortcutLocations(&env, GetProfilePath(), GetAppId());
     // Doesn't count as being in applications menu.
     EXPECT_FALSE(result.on_desktop);
     EXPECT_EQ(APP_MENU_LOCATION_HIDDEN, result.applications_menu_location);
     EXPECT_FALSE(result.in_quick_launch_bar);
+    EXPECT_FALSE(result.in_startup);
   }
 
   // Shortcut on desktop and in applications directory.
   {
-    base::ScopedTempDir temp_dir1;
-    ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-    base::FilePath desktop_path = temp_dir1.GetPath();
-
-    base::ScopedTempDir temp_dir2;
-    ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
-    base::FilePath apps_path = temp_dir2.GetPath().Append("applications");
-
+    ScopedDesktopPath scoped_desktop_path;
+    base::ScopedPathOverride user_desktop_override(
+        base::DIR_USER_DESKTOP, scoped_desktop_path.GetPath());
+    ScopedApplicationsPath scoped_applications_path;
     MockEnvironment env;
-    ASSERT_TRUE(base::CreateDirectory(desktop_path));
-    ASSERT_TRUE(base::WriteFile(desktop_path.Append(kTemplateFilename), ""));
-    env.Set("XDG_DATA_HOME", temp_dir2.GetPath().value());
-    ASSERT_TRUE(base::CreateDirectory(apps_path));
-    ASSERT_TRUE(base::WriteFile(apps_path.Append(kTemplateFilename), ""));
-    ShortcutLocations result = GetExistingShortcutLocations(
-        &env, kProfilePath, kExtensionId, desktop_path);
+
+    env.Set("XDG_DATA_HOME",
+            scoped_applications_path.GetDataHomePath().value());
+    CreateShortcutInPath(scoped_desktop_path.GetPath());
+    CreateShortcutInPath(scoped_applications_path.GetPath());
+
+    ShortcutLocations result =
+        GetExistingShortcutLocations(&env, GetProfilePath(), GetAppId());
     EXPECT_TRUE(result.on_desktop);
     EXPECT_EQ(APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
               result.applications_menu_location);
     EXPECT_FALSE(result.in_quick_launch_bar);
+    EXPECT_FALSE(result.in_startup);
   }
 }
 
-TEST(ShellIntegrationTest, GetExtensionShortcutFilename) {
-  base::FilePath kProfilePath("a/b/c/Profile Name?");
-  const char kExtensionId[] = "extensionid";
-  EXPECT_EQ(base::FilePath("chrome-extensionid-Profile_Name_.desktop"),
-            GetAppShortcutFilename(kProfilePath, kExtensionId));
+TEST_F(WebAppShortcutLinuxTest, GetExtensionShortcutFilename) {
+  EXPECT_EQ(base::FilePath("chrome-extensionid-Profile_1.desktop"),
+            GetAppShortcutFilename(GetProfilePath(), "extensionid"));
+}
+
+TEST_F(WebAppShortcutLinuxTest, DeleteDesktopShortcuts) {
+  ScopedDesktopPath scoped_desktop_path;
+  base::FilePath desktop_shortcut_path =
+      CreateShortcutInPath(scoped_desktop_path.GetPath());
+  base::ScopedPathOverride user_desktop_override(base::DIR_USER_DESKTOP,
+                                                 scoped_desktop_path.GetPath());
+
+  int invoke_count = 0;
+  auto DeleteApplicationsLaunchXdgUtility = base::BindLambdaForTesting(
+      [&](const std::vector<std::string>& argv, int* exit_code) -> bool {
+        EXPECT_EQ(invoke_count, 0);
+        invoke_count++;
+        ValidateDeleteApplicationsLaunchXdgUtility(argv, exit_code);
+        return true;
+      });
+
+  SetLaunchXdgUtilityForTesting(DeleteApplicationsLaunchXdgUtility);
+
+  EXPECT_TRUE(base::PathExists(desktop_shortcut_path));
+  EXPECT_TRUE(DeleteDesktopShortcuts(GetProfilePath(), GetAppId()));
+  EXPECT_EQ(invoke_count, 1);
+  EXPECT_FALSE(base::PathExists(desktop_shortcut_path));
+}
+
+TEST_F(WebAppShortcutLinuxTest, DeleteAllDesktopShortcuts) {
+  ScopedDesktopPath scoped_desktop_path;
+  base::FilePath desktop_shortcut_path =
+      CreateShortcutInPath(scoped_desktop_path.GetPath());
+  base::ScopedPathOverride user_desktop_override(base::DIR_USER_DESKTOP,
+                                                 scoped_desktop_path.GetPath());
+
+  ScopedApplicationsPath scoped_applications_path;
+  base::FilePath application_shortcut_path =
+      CreateShortcutInPath(scoped_applications_path.GetPath());
+  MockEnvironment env;
+  env.Set("XDG_DATA_HOME", scoped_applications_path.GetDataHomePath().value());
+
+  int invoke_count = 0;
+  auto DeleteApplicationsLaunchXdgUtility = base::BindLambdaForTesting(
+      [&](const std::vector<std::string>& argv, int* exit_code) -> bool {
+        EXPECT_EQ(invoke_count, 0);
+        invoke_count++;
+        ValidateDeleteApplicationsLaunchXdgUtility(argv, exit_code);
+        return true;
+      });
+
+  SetLaunchXdgUtilityForTesting(DeleteApplicationsLaunchXdgUtility);
+
+  EXPECT_TRUE(base::PathExists(desktop_shortcut_path));
+  EXPECT_TRUE(DeleteAllDesktopShortcuts(&env, GetProfilePath()));
+  EXPECT_EQ(invoke_count, 1);
+  EXPECT_FALSE(base::PathExists(desktop_shortcut_path));
+}
+
+TEST_F(WebAppShortcutLinuxTest, CreateDesktopShortcut) {
+  ScopedDesktopPath scoped_desktop_path;
+  ScopedApplicationsPath scoped_applications_path;
+  base::ScopedPathOverride user_desktop_override(base::DIR_USER_DESKTOP,
+                                                 scoped_desktop_path.GetPath());
+  MockEnvironment env;
+  env.Set("XDG_DATA_HOME", scoped_applications_path.GetDataHomePath().value());
+
+  int invoke_count = 0;
+  LaunchXdgUtilityForTesting CreateDesktopShortcutLaunchXdgUtility =
+      base::BindLambdaForTesting([&](const std::vector<std::string>& argv,
+                                     int* exit_code) -> bool {
+        ValidateCreateDesktopShortcutLaunchXdgUtility(
+            argv, exit_code, scoped_applications_path.GetPath(), invoke_count);
+        invoke_count++;
+
+        if (invoke_count < 4)
+          SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+        return true;
+      });
+
+  SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+
+  std::unique_ptr<ShortcutInfo> shortcut_info = GetShortcutInfo();
+  ShortcutLocations locations;
+  locations.on_desktop = true;
+  locations.applications_menu_location = APP_MENU_LOCATION_SUBDIR_CHROMEAPPS;
+
+  EXPECT_TRUE(CreateDesktopShortcut(&env, *shortcut_info, locations));
+  EXPECT_EQ(invoke_count, 4);
+
+  // At this point, we've already validated creation in the Application menu
+  // because of the hook into XdgUtilityForTesting.
+  // Validate the shortcut was created, and the contents are what we expect
+  // them to be.
+  std::string expected_contents =
+      shell_integration_linux::GetDesktopFileContents(
+          shell_integration_linux::internal::GetChromeExePath(),
+          GenerateApplicationNameFromInfo(*shortcut_info), shortcut_info->url,
+          shortcut_info->extension_id, shortcut_info->title,
+          "chrome-test_extension-Profile_1", shortcut_info->profile_path, "",
+          "", false);
+
+  base::FilePath desktop_shortcut_path =
+      scoped_desktop_path.GetPath().Append(GetTemplateFilename());
+  ASSERT_TRUE(base::PathExists(desktop_shortcut_path));
+
+  std::string actual_contents;
+  ASSERT_TRUE(base::ReadFileToString(desktop_shortcut_path, &actual_contents));
+  EXPECT_EQ(expected_contents, actual_contents);
+}
+
+TEST_F(WebAppShortcutLinuxTest, CreateDesktopShortcutEmptyExtension) {
+  ScopedDesktopPath scoped_desktop_path;
+  ScopedApplicationsPath scoped_applications_path;
+  base::ScopedPathOverride user_desktop_override(base::DIR_USER_DESKTOP,
+                                                 scoped_desktop_path.GetPath());
+  MockEnvironment env;
+  env.Set("XDG_DATA_HOME", scoped_applications_path.GetDataHomePath().value());
+
+  int invoke_count = 0;
+  LaunchXdgUtilityForTesting CreateDesktopShortcutLaunchXdgUtility =
+      base::BindLambdaForTesting([&](const std::vector<std::string>& argv,
+                                     int* exit_code) -> bool {
+        EXPECT_TRUE(exit_code);
+        *exit_code = 0;
+
+        // There are 3 calls to this function:
+        //  case 0) install the icon for the new shortcut
+        //  case 1) install the new shortcut
+        //  case 2) update desktop database
+        EXPECT_LE(invoke_count, 3);
+
+        std::vector<std::string> expected_argv;
+        switch (invoke_count) {
+          case 0:
+            // The icon is generated to a temporary path, but the file name
+            // should be known Confirm the file name is what we expect, and use
+            // the parameter passed in.
+            EXPECT_EQ(argv.size(), 8u);
+            EXPECT_TRUE(argv[6].find("chrome-https___example.com_.png") !=
+                        std::string::npos);
+            expected_argv.push_back("xdg-icon-resource");
+            expected_argv.push_back("install");
+            expected_argv.push_back("--mode");
+            expected_argv.push_back("user");
+            expected_argv.push_back("--size");
+            expected_argv.push_back("512");
+            expected_argv.push_back(argv[6]);
+            expected_argv.push_back("chrome-https___example.com_");
+            break;
+
+          case 1:
+            // The desktop file is generated to a temporary path, but the file
+            // name should be known Confirm the file name is what we expect, and
+            // use the parameter passed in.
+            EXPECT_EQ(argv.size(), 6u);
+            EXPECT_TRUE(argv[4].find("chrome-apps.directory") !=
+                        std::string::npos);
+            EXPECT_TRUE(argv[5].find("chrome-https___example.com_.desktop") !=
+                        std::string::npos);
+
+            expected_argv.push_back("xdg-desktop-menu");
+            expected_argv.push_back("install");
+            expected_argv.push_back("--mode");
+            expected_argv.push_back("user");
+            expected_argv.push_back(argv[4]);
+            expected_argv.push_back(argv[5]);
+            break;
+
+          case 2:
+            expected_argv.push_back("update-desktop-database");
+            expected_argv.push_back(scoped_applications_path.GetPath().value());
+            break;
+        }
+
+        invoke_count++;
+        EXPECT_EQ(expected_argv, argv);
+        if (invoke_count < 3)
+          SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+        return true;
+      });
+
+  SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+
+  std::unique_ptr<ShortcutInfo> shortcut_info = GetShortcutInfo();
+  shortcut_info->extension_id = "";
+  shortcut_info->url = GURL("https://example.com");
+
+  ShortcutLocations locations;
+  locations.on_desktop = true;
+  locations.applications_menu_location = APP_MENU_LOCATION_SUBDIR_CHROMEAPPS;
+
+  EXPECT_TRUE(CreateDesktopShortcut(&env, *shortcut_info, locations));
+  EXPECT_EQ(invoke_count, 3);
+
+  // At this point, we've already validated creation in the Application menu
+  // because of the hook into XdgUtilityForTesting.
+  // Validate the shortcut was created, and the contents are what we expect
+  // them to be.
+  std::string expected_contents =
+      shell_integration_linux::GetDesktopFileContents(
+          shell_integration_linux::internal::GetChromeExePath(),
+          GenerateApplicationNameFromInfo(*shortcut_info), shortcut_info->url,
+          shortcut_info->extension_id, shortcut_info->title,
+          "chrome-https___example.com_", shortcut_info->profile_path, "", "",
+          false);
+
+  base::FilePath desktop_shortcut_path = scoped_desktop_path.GetPath().Append(
+      "chrome-https___example.com_.desktop");
+  ASSERT_TRUE(base::PathExists(desktop_shortcut_path));
+
+  std::string actual_contents;
+  ASSERT_TRUE(base::ReadFileToString(desktop_shortcut_path, &actual_contents));
+  EXPECT_EQ(expected_contents, actual_contents);
+}
+
+TEST_F(WebAppShortcutLinuxTest, UpdateDesktopShortcuts) {
+  ScopedDesktopPath scoped_desktop_path;
+  ScopedApplicationsPath scoped_applications_path;
+  base::ScopedPathOverride user_desktop_override(base::DIR_USER_DESKTOP,
+                                                 scoped_desktop_path.GetPath());
+  MockEnvironment env;
+  env.Set("XDG_DATA_HOME", scoped_applications_path.GetDataHomePath().value());
+  CreateShortcutInPath(scoped_desktop_path.GetPath());
+  CreateShortcutInPath(scoped_applications_path.GetPath());
+
+  int invoke_count = 0;
+  LaunchXdgUtilityForTesting CreateDesktopShortcutLaunchXdgUtility =
+      base::BindLambdaForTesting([&](const std::vector<std::string>& argv,
+                                     int* exit_code) -> bool {
+        ValidateCreateDesktopShortcutLaunchXdgUtility(
+            argv, exit_code, scoped_applications_path.GetPath(), invoke_count);
+        invoke_count++;
+
+        if (invoke_count < 4)
+          SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+        return true;
+      });
+
+  SetLaunchXdgUtilityForTesting(CreateDesktopShortcutLaunchXdgUtility);
+
+  std::unique_ptr<ShortcutInfo> shortcut_info = GetShortcutInfo();
+
+  UpdateDesktopShortcuts(&env, *shortcut_info);
+  EXPECT_EQ(invoke_count, 4);
+
+  // At this point, we've already validated creation in the Application menu
+  // because of the hook into XdgUtilityForTesting.
+  // Validate the shortcut was created, and the contents are what we expect
+  // them to be.
+  std::string expected_contents =
+      shell_integration_linux::GetDesktopFileContents(
+          shell_integration_linux::internal::GetChromeExePath(),
+          GenerateApplicationNameFromInfo(*shortcut_info), shortcut_info->url,
+          shortcut_info->extension_id, shortcut_info->title,
+          "chrome-test_extension-Profile_1", shortcut_info->profile_path, "",
+          "", false);
+
+  base::FilePath desktop_shortcut_path =
+      scoped_desktop_path.GetPath().Append(GetTemplateFilename());
+  ASSERT_TRUE(base::PathExists(desktop_shortcut_path));
+
+  std::string actual_contents;
+  ASSERT_TRUE(base::ReadFileToString(desktop_shortcut_path, &actual_contents));
+  EXPECT_EQ(expected_contents, actual_contents);
 }
 
 }  // namespace web_app
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 51ac4d5..dc4ba1e4 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1606240669-c1104e164a95943470032f861bc56133b735d819.profdata
+chrome-linux-master-1606262372-53701711e1f3f7b0d49627ad74cc045279aff3ad.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b5c54c2..00c2c01f3 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1606240669-251229982c87402ee7b9ccf8ab49774406a74762.profdata
+chrome-mac-master-1606262372-c28fabe0f518396be3e19b31d10fd57f4542b836.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 67842c6..459b252 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1606218923-28e4a6cb560c6a9acc44daf784662f70e5c57403.profdata
+chrome-win64-master-1606240669-a966a0de7533a2c29e2a147761a10e8425d1cfe7.profdata
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl
index ffdfa860..ec904a2 100644
--- a/chrome/common/extensions/api/file_manager_private.idl
+++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -169,10 +169,8 @@
   failed,
   // No URL is specified.
   empty,
-  // The task was a |plugin_vm| task, and the file was in a unshared directory
-  failed_plugin_vm_task_directory_not_shared,
-  // The task was a |plugin_vm| task, and the file was in an external drive.
-  failed_plugin_vm_task_external_drive
+  // The task was a |plugin_vm| task, and the file was in an unshared directory
+  failed_plugin_vm_directory_not_shared
 };
 
 // Drive share type.
@@ -254,7 +252,8 @@
   enable,
   disable,
   share,
-  unshare
+  unshare,
+  drop_failed_plugin_vm_directory_not_shared
 };
 
 enum ProviderSource {
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 49ea9dad..72394e0 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1056,6 +1056,11 @@
 const char kEduCoexistenceArcMigrationCompleted[] =
     "account_manager.edu_coexistence_arc_migration_completed";
 
+// Boolean pref indicating whether reusing the Chrome OS login credentials for
+// network authentication is allowed. Note: currently only used for managed
+// proxies secured with NTLM authentication.
+const char kIntegratedWebAuthenticationAllowed[] =
+    "auth.integrated_web_authentication_allowed";
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // A boolean pref set to true if a Home button to open the Home pages should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 83b0b288..5cd64a09 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -796,6 +796,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 extern const char kKerberosEnabled[];
+extern const char kIntegratedWebAuthenticationAllowed[];
 #endif
 
 extern const char kCertRevocationCheckingEnabled[];
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index fb7fa9f..03d9d4c 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/buildflags_paint_preview.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//chrome/common/features.gni")
 import("//components/nacl/features.gni")
@@ -36,7 +37,7 @@
     "//url/mojom:url_mojom_gurl_js",
     "//url/mojom:url_mojom_origin_js",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "//chromeos/components/remote_apps/mojom:mojom_js",
       "//chromeos/services/ime/public/mojom:mojom_js",
@@ -137,6 +138,7 @@
 
   deps = [
     "//base/allocator:buildflags",
+    "//build:chromeos_buildflags",
     "//chrome:resources",
     "//chrome:strings",
     "//chrome/common",
@@ -341,7 +343,7 @@
     deps += [ "//third_party/wtl" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "extensions/file_browser_handler_custom_bindings.cc",
       "extensions/file_browser_handler_custom_bindings.h",
@@ -387,7 +389,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "chromeos_delayed_callback_group.cc",
       "chromeos_delayed_callback_group.h",
@@ -396,7 +398,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "performance_manager/mechanisms/tcmalloc_tunables_impl.cc",
       "performance_manager/mechanisms/tcmalloc_tunables_impl.h",
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 1856a59..e2d2b55 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/test/base/chrome_render_view_test.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/form_cache.h"
@@ -3069,7 +3070,7 @@
 }
 
 // TODO(crbug.com/616730) Flaky.
-#if defined(OS_CHROMEOS) || defined(OS_MAC)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC)
 #define MAYBE_WebFormElementToFormDataTooManyFields \
   DISABLED_WebFormElementToFormDataTooManyFields
 #else
diff --git a/chrome/renderer/browser_exposed_renderer_interfaces.cc b/chrome/renderer/browser_exposed_renderer_interfaces.cc
index 02b8ac4..042f74e9 100644
--- a/chrome/renderer/browser_exposed_renderer_interfaces.cc
+++ b/chrome/renderer/browser_exposed_renderer_interfaces.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/renderer/chrome_render_thread_observer.h"
 #include "chrome/renderer/media/webrtc_logging_agent_impl.h"
@@ -21,13 +22,13 @@
 #include "components/spellcheck/renderer/spellcheck.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/allocator/buildflags.h"
 #if BUILDFLAG(USE_TCMALLOC)
 #include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h"
 #include "chrome/renderer/performance_manager/mechanisms/tcmalloc_tunables_impl.h"
 #endif  // BUILDFLAG(USE_TCMALLOC)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -62,14 +63,14 @@
   binders->Add(base::BindRepeating(&BindWebRTCLoggingAgent, client),
                base::SequencedTaskRunnerHandle::Get());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #if BUILDFLAG(USE_TCMALLOC)
   binders->Add(
       base::BindRepeating(
           &performance_manager::mechanism::TcmallocTunablesImpl::Create),
       base::SequencedTaskRunnerHandle::Get());
 #endif  // BUILDFLAG(USE_TCMALLOC)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   binders->Add(base::BindRepeating(&BindSpellChecker, client),
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 18b0801..8f7a15a 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -24,6 +24,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_content_client.h"
@@ -907,7 +908,7 @@
                 blink::mojom::ConsoleMessageLevel::kError, error_message));
             placeholder = create_blocked_plugin(
                 IDR_BLOCKED_PLUGIN_HTML,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
                 l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED));
 #else
                 l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name));
@@ -1466,10 +1467,10 @@
   // Web Share is conditionally enabled here in chrome/, to avoid it being
   // made available in other clients of content/ that do not have a Web Share
   // Mojo implementation (e.g. WebView).  Web Share is shipped on Android.
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
   if (base::FeatureList::IsEnabled(features::kWebShare))
 #endif
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) || defined(OS_ANDROID)
     blink::WebRuntimeFeatures::EnableWebShare(true);
 #endif
 
@@ -1616,7 +1617,7 @@
            // TODO(crbug.com/1110954): Remove when migrated away from HTML
            // imports.
            host_piece == chrome::kChromeUIBluetoothInternalsHost ||
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
            // TODO(crbug.com/1111430): Remove when migrated to Polymer3.
            host_piece == chrome::kChromeUIAccountManagerErrorHost ||
            host_piece == chrome::kChromeUIAccountManagerWelcomeHost ||
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc
index d553f2f7..71dd600 100644
--- a/chrome/renderer/chrome_render_thread_observer.cc
+++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -28,6 +28,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/cache_stats_recorder.mojom.h"
 #include "chrome/common/child_process_logging.h"
 #include "chrome/common/chrome_paths.h"
@@ -58,7 +59,7 @@
 #include "chrome/renderer/extensions/extension_localization_peer.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/renderer/chromeos_merge_session_loader_throttle.h"
 #endif
 
@@ -118,7 +119,7 @@
   DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
 };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 scoped_refptr<base::SequencedTaskRunner> GetCallbackGroupTaskRunner() {
   content::ChildThread* child_thread = content::ChildThread::Get();
   if (child_thread)
@@ -127,13 +128,13 @@
   // This will happen when running via tests.
   return base::SequencedTaskRunnerHandle::Get();
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
 
 bool ChromeRenderThreadObserver::is_incognito_process_ = false;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // static
 scoped_refptr<ChromeRenderThreadObserver::ChromeOSListener>
 ChromeRenderThreadObserver::ChromeOSListener::Create(
@@ -180,7 +181,7 @@
         chromeos_listener_receiver) {
   receiver_.Bind(std::move(chromeos_listener_receiver));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 chrome::mojom::DynamicParams* GetDynamicConfigParams() {
   static base::NoDestructor<chrome::mojom::DynamicParams> dynamic_params;
@@ -224,12 +225,12 @@
     mojo::PendingReceiver<chrome::mojom::ChromeOSListener>
         chromeos_listener_receiver) {
   is_incognito_process_ = is_incognito_process;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (chromeos_listener_receiver) {
     chromeos_listener_ =
         ChromeOSListener::Create(std::move(chromeos_listener_receiver));
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void ChromeRenderThreadObserver::SetConfiguration(
diff --git a/chrome/renderer/chrome_render_thread_observer.h b/chrome/renderer/chrome_render_thread_observer.h
index 3495bab8..22582633 100644
--- a/chrome/renderer/chrome_render_thread_observer.h
+++ b/chrome/renderer/chrome_render_thread_observer.h
@@ -10,6 +10,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/renderer_configuration.mojom.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "content/public/renderer/render_thread_observer.h"
@@ -18,9 +19,9 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/renderer/chromeos_delayed_callback_group.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace content {
 class ResourceDispatcherDelegate;
@@ -37,7 +38,7 @@
 class ChromeRenderThreadObserver : public content::RenderThreadObserver,
                                    public chrome::mojom::RendererConfiguration {
  public:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // A helper class to handle Mojo calls that need to be dispatched to the IO
   // thread instead of the main thread as is the norm.
   // This class is thread-safe.
@@ -75,7 +76,7 @@
 
     DISALLOW_COPY_AND_ASSIGN(ChromeOSListener);
   };
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   ChromeRenderThreadObserver();
   ~ChromeRenderThreadObserver() override;
@@ -94,11 +95,11 @@
     return visited_link_reader_.get();
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   scoped_refptr<ChromeOSListener> chromeos_listener() const {
     return chromeos_listener_;
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
  private:
   // content::RenderThreadObserver:
@@ -128,11 +129,11 @@
   mojo::AssociatedReceiverSet<chrome::mojom::RendererConfiguration>
       renderer_configuration_receivers_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Only set if the Chrome OS merge session was running when the renderer
   // was started.
   scoped_refptr<ChromeOSListener> chromeos_listener_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   DISALLOW_COPY_AND_ASSIGN(ChromeRenderThreadObserver);
 };
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index 11fa44e..405f09b2 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/strings/string_number_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
@@ -42,7 +43,7 @@
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/web/web_security_policy.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
 #include "chrome/renderer/extensions/file_manager_private_custom_bindings.h"
 #include "chrome/renderer/extensions/platform_keys_natives.h"
@@ -66,7 +67,7 @@
       "sync_file_system",
       std::unique_ptr<NativeHandler>(
           new extensions::SyncFileSystemCustomBindings(context)));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   module_system->RegisterNativeHandler(
       "file_browser_handler",
       std::unique_ptr<NativeHandler>(
@@ -79,7 +80,7 @@
       "platform_keys_natives",
       std::unique_ptr<NativeHandler>(
           new extensions::PlatformKeysNatives(context)));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   module_system->RegisterNativeHandler(
       "notifications_private",
       std::unique_ptr<NativeHandler>(
@@ -137,7 +138,7 @@
   source_map->RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   source_map->RegisterSource("certificateProvider",
                              IDR_CERTIFICATE_PROVIDER_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("enterprise.platformKeys",
@@ -187,7 +188,7 @@
                              IDR_REMOTE_APPS_BINDINGS_JS);
   source_map->RegisterSource("url/mojom/url.mojom-lite",
                              IDR_MOJO_URL_MOJOM_LITE_JS);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   source_map->RegisterSource(
       "webrtcDesktopCapturePrivate",
@@ -272,7 +273,7 @@
   bindings->GetHooksForAPI("accessibilityPrivate")
       ->SetDelegate(
           std::make_unique<extensions::AccessibilityPrivateHooksDelegate>());
-#if defined(OS_CHROMEOS) && defined(USE_CUPS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && defined(USE_CUPS)
   bindings->GetHooksForAPI("printing")
       ->SetDelegate(std::make_unique<extensions::PrintingHooksDelegate>());
 #endif
diff --git a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc
index 97eb9fd..81b7ad4 100644
--- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc
+++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/check.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "extensions/renderer/script_context.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/web_dom_file_system.h"
@@ -33,53 +34,53 @@
     ScriptContext* context) {
 // TODO(zelidrag): Make this magic work on other platforms when file browser
 // matures enough on ChromeOS.
-#if defined(OS_CHROMEOS)
-    CHECK(args.Length() == 1);
-    CHECK(args[0]->IsObject());
-    v8::Local<v8::Object> file_def = args[0].As<v8::Object>();
-    v8::Isolate* isolate = args.GetIsolate();
-    v8::Local<v8::Context> v8_context = context->v8_context();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  CHECK(args.Length() == 1);
+  CHECK(args[0]->IsObject());
+  v8::Local<v8::Object> file_def = args[0].As<v8::Object>();
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::Local<v8::Context> v8_context = context->v8_context();
 
-    std::string file_system_name(*v8::String::Utf8Value(
-        isolate, file_def
-                     ->Get(v8_context, v8::String::NewFromUtf8(
-                                           isolate, "fileSystemName",
-                                           v8::NewStringType::kInternalized)
-                                           .ToLocalChecked())
-                     .ToLocalChecked()));
-    GURL file_system_root(*v8::String::Utf8Value(
-        isolate, file_def
-                     ->Get(v8_context, v8::String::NewFromUtf8(
-                                           isolate, "fileSystemRoot",
-                                           v8::NewStringType::kInternalized)
-                                           .ToLocalChecked())
-                     .ToLocalChecked()));
-    std::string file_full_path(*v8::String::Utf8Value(
-        isolate, file_def
-                     ->Get(v8_context, v8::String::NewFromUtf8(
-                                           isolate, "fileFullPath",
-                                           v8::NewStringType::kInternalized)
-                                           .ToLocalChecked())
-                     .ToLocalChecked()));
-    bool is_directory =
-        file_def
-            ->Get(v8_context,
-                  v8::String::NewFromUtf8(isolate, "fileIsDirectory",
-                                          v8::NewStringType::kInternalized)
-                      .ToLocalChecked())
-            .ToLocalChecked()
-            ->BooleanValue(isolate);
-    blink::WebDOMFileSystem::EntryType entry_type =
-        is_directory ? blink::WebDOMFileSystem::kEntryTypeDirectory
-                     : blink::WebDOMFileSystem::kEntryTypeFile;
-    blink::WebLocalFrame* webframe =
-        blink::WebLocalFrame::FrameForContext(v8_context);
-    args.GetReturnValue().Set(
-        blink::WebDOMFileSystem::Create(
-            webframe, blink::kWebFileSystemTypeExternal,
-            blink::WebString::FromUTF8(file_system_name), file_system_root)
-            .CreateV8Entry(blink::WebString::FromUTF8(file_full_path),
-                           entry_type, args.Holder(), isolate));
+  std::string file_system_name(*v8::String::Utf8Value(
+      isolate, file_def
+                   ->Get(v8_context, v8::String::NewFromUtf8(
+                                         isolate, "fileSystemName",
+                                         v8::NewStringType::kInternalized)
+                                         .ToLocalChecked())
+                   .ToLocalChecked()));
+  GURL file_system_root(*v8::String::Utf8Value(
+      isolate, file_def
+                   ->Get(v8_context, v8::String::NewFromUtf8(
+                                         isolate, "fileSystemRoot",
+                                         v8::NewStringType::kInternalized)
+                                         .ToLocalChecked())
+                   .ToLocalChecked()));
+  std::string file_full_path(*v8::String::Utf8Value(
+      isolate, file_def
+                   ->Get(v8_context, v8::String::NewFromUtf8(
+                                         isolate, "fileFullPath",
+                                         v8::NewStringType::kInternalized)
+                                         .ToLocalChecked())
+                   .ToLocalChecked()));
+  bool is_directory =
+      file_def
+          ->Get(v8_context,
+                v8::String::NewFromUtf8(isolate, "fileIsDirectory",
+                                        v8::NewStringType::kInternalized)
+                    .ToLocalChecked())
+          .ToLocalChecked()
+          ->BooleanValue(isolate);
+  blink::WebDOMFileSystem::EntryType entry_type =
+      is_directory ? blink::WebDOMFileSystem::kEntryTypeDirectory
+                   : blink::WebDOMFileSystem::kEntryTypeFile;
+  blink::WebLocalFrame* webframe =
+      blink::WebLocalFrame::FrameForContext(v8_context);
+  args.GetReturnValue().Set(
+      blink::WebDOMFileSystem::Create(
+          webframe, blink::kWebFileSystemTypeExternal,
+          blink::WebString::FromUTF8(file_system_name), file_system_root)
+          .CreateV8Entry(blink::WebString::FromUTF8(file_full_path), entry_type,
+                         args.Holder(), isolate));
 #endif
 }
 
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index 3e5362e9..93c95a3f 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -15,6 +15,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/renderer/chrome_render_thread_observer.h"
 #include "components/cdm/renderer/external_clear_key_key_system_properties.h"
 #include "components/cdm/renderer/widevine_key_system_properties.h"
@@ -201,7 +202,7 @@
   }
 
 // On ChromeOS, platform verification is similar to CDM host verification.
-#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) || defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) || BUILDFLAG(IS_CHROMEOS_ASH)
   bool cdm_host_verification_potentially_supported = true;
 #else
   bool cdm_host_verification_potentially_supported = false;
@@ -214,7 +215,7 @@
     return EmeSessionTypeSupport::NOT_SUPPORTED;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, platform verification (similar to CDM host verification)
   // requires identifier to be allowed.
   // TODO(jrummell): Currently the ChromeOS CDM does not require storage ID
@@ -228,7 +229,7 @@
   // Storage ID not implemented, so no support for persistent license.
   DVLOG(2) << __func__ << ": Not supported without CDM storage ID.";
   return EmeSessionTypeSupport::NOT_SUPPORTED;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 static void AddWidevine(
@@ -263,7 +264,7 @@
   auto max_audio_robustness = Robustness::SW_SECURE_CRYPTO;
   auto max_video_robustness = Robustness::SW_SECURE_DECODE;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On ChromeOS, we support HW_SECURE_ALL even without hardware secure codecs.
   // See WidevineKeySystemProperties::GetRobustnessConfigRule().
   max_audio_robustness = Robustness::HW_SECURE_ALL;
@@ -298,7 +299,7 @@
   // Others.
   auto persistent_state_support = EmeFeatureSupport::REQUESTABLE;
   auto distinctive_identifier_support = EmeFeatureSupport::NOT_SUPPORTED;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   distinctive_identifier_support = EmeFeatureSupport::REQUESTABLE;
 #endif
 
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc
index ea47d97..1daaf655 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.cc
+++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -12,6 +12,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/common/google_url_loader_throttle.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/renderer/chrome_render_frame_observer.h"
@@ -38,9 +39,9 @@
 #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/renderer/chromeos_merge_session_loader_throttle.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
 
@@ -205,11 +206,11 @@
 #endif
       ChromeRenderThreadObserver::GetDynamicParams()));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   throttles.push_back(std::make_unique<MergeSessionLoaderThrottle>(
       chrome_content_renderer_client_->GetChromeObserver()
           ->chromeos_listener()));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   auto throttle = subresource_redirect::SubresourceRedirectURLLoaderThrottle::
       MaybeCreateThrottle(request, render_frame_id);
diff --git a/chrome/services/speech/soda/soda_client.cc b/chrome/services/speech/soda/soda_client.cc
index 25c99d3..30c99cc 100644
--- a/chrome/services/speech/soda/soda_client.cc
+++ b/chrome/services/speech/soda/soda_client.cc
@@ -18,6 +18,7 @@
       sample_rate_(0),
       channel_count_(0) {}
 
+NO_SANITIZE("cfi-icall")
 SodaClient::~SodaClient() {
   DCHECK(soda_async_handle_);
   DCHECK(delete_soda_func_);
@@ -25,6 +26,7 @@
     delete_soda_func_(soda_async_handle_);
 }
 
+NO_SANITIZE("cfi-icall")
 void SodaClient::AddAudio(const char* audio_buffer, int audio_buffer_size) {
   DCHECK(soda_async_handle_);
   DCHECK(add_audio_func_);
@@ -35,6 +37,7 @@
   return sample_rate != sample_rate_ || channel_count != channel_count_;
 }
 
+NO_SANITIZE("cfi-icall")
 void SodaClient::Reset(const SodaConfig config) {
   DCHECK(soda_async_handle_);
   DCHECK(create_soda_func_);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6de801c..6d95018 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -535,6 +535,7 @@
       ":test_support",
       ":test_support_java",
       ":test_support_ui_android",
+      "//build:chromeos_buildflags",
       "//chrome:chrome_android_core",
       "//chrome/android:app_hooks_java",
       "//chrome/browser/metrics:test_support",
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 44e5f64..f30fb6a 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -95,16 +95,6 @@
 _OS_SPECIFIC_FILTER['win'] = [
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=299
     'ChromeLogPathCapabilityTest.testChromeLogPath',
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=1011095
-    'ChromeDownloadDirTest.testFileDownloadAfterTabHeadless',
-    'ChromeDownloadDirTest.testFileDownloadWithClickHeadless',
-    'ChromeDownloadDirTest.testFileDownloadWithGetHeadless',
-    'RemoteBrowserTest.testConnectToRemoteBrowserLiteralAddressHeadless',
-    # HeadlessInvalidCertificateTest is sometimes flaky.
-    'HeadlessInvalidCertificateTest.*',
-    # Similar issues with HeadlessChromeDriverTest.
-    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=3519
-    'HeadlessChromeDriverTest.*',
 ]
 _OS_SPECIFIC_FILTER['linux'] = [
 ]
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index b37a41f..1438916 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8285,5 +8285,17 @@
         }
       }
     ]
+  },
+  "IntegratedWebAuthenticationAllowed": {
+    "os": ["chromeos"],
+    "can_be_recommended": false,
+    "policy_pref_mapping_test": [
+      {
+        "policies": { "IntegratedWebAuthenticationAllowed": false },
+        "prefs": {
+          "auth.integrated_web_authentication_allowed": { "local_state": true }
+        }
+      }
+    ]
   }
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
index 4352c80..60a3374 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/fake_system_data_provider_test.js
@@ -39,6 +39,7 @@
       marketingName: 'Bestest 1000',
       totalMemoryKib: 9999,
       cpuThreadsCount: 4,
+      cpuMaxClockSpeedKhz: 1000,
       versionInfo: version,
       deviceCapabilities: capabilities,
     };
diff --git a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
index 2ddbeee8..4638a2e 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
@@ -53,12 +53,12 @@
   }
 
   /**
-   * Get margin_ private member for testing.
+   * Get padding_ private member for testing.
    * @suppress {visibility} // access private member
    */
-  function getMargins() {
+  function getPaddings() {
     assertTrue(!!realtimeCpuChartElement);
-    return realtimeCpuChartElement.margin_;
+    return realtimeCpuChartElement.padding_;
   }
 
   /**
@@ -110,7 +110,7 @@
 
       // Margins are in effect.
       assertEquals(
-          `translate(${getMargins().left},${getMargins().top})`,
+          `translate(${getPaddings().left},${getPaddings().top})`,
           chartGroup.getAttribute('transform'));
     });
   });
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index ec77bca..d13bf42 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -7,6 +7,7 @@
 import {RoutineName, RoutineResult, StandardRoutineResult} from 'chrome://diagnostics/diagnostics_types.js';
 import {ExecutionProgress, ResultStatusItem} from 'chrome://diagnostics/routine_list_executor.js';
 import {BadgeType} from 'chrome://diagnostics/text_badge.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.m.js';
@@ -116,8 +117,11 @@
     const item = createIncompleteStatus(
         RoutineName.kCpuStress, ExecutionProgress.kNotStarted);
     return initializeEntryWithItem(item).then(() => {
-      // TODO(zentaro): Localize the test.
-      assertEquals(getNameText(), 'kCpuStress');
+      assertEquals(
+          getNameText(),
+          loadTimeData.getStringF(
+              'routineNameText',
+              loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should be empty if the test is not started.
       // TODO(joonbug): Utilize isVisible util function.
@@ -129,8 +133,11 @@
     const item = createIncompleteStatus(
         RoutineName.kCpuStress, ExecutionProgress.kRunning);
     return initializeEntryWithItem(item).then(() => {
-      // TODO(zentaro): Localize the test.
-      assertEquals(getNameText(), 'kCpuStress');
+      assertEquals(
+          getNameText(),
+          loadTimeData.getStringF(
+              'routineNameText',
+              loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should be running.
       assertEquals(getStatusBadge().value, 'RUNNING');
@@ -144,8 +151,11 @@
           simpleResult: StandardRoutineResult.kTestPassed
         }));
     return initializeEntryWithItem(item).then(() => {
-      // TODO(zentaro): Localize the test.
-      assertEquals(getNameText(), 'kCpuStress');
+      assertEquals(
+          getNameText(),
+          loadTimeData.getStringF(
+              'routineNameText',
+              loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should show the passed result.
       assertEquals(getStatusBadge().value, 'SUCCESS');
@@ -159,8 +169,11 @@
           simpleResult: StandardRoutineResult.kTestFailed
         }));
     return initializeEntryWithItem(item).then(() => {
-      // TODO(zentaro): Localize the test.
-      assertEquals(getNameText(), 'kCpuStress');
+      assertEquals(
+          getNameText(),
+          loadTimeData.getStringF(
+              'routineNameText',
+              loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should show the passed result.
       assertEquals(getStatusBadge().value, 'FAILED');
@@ -179,8 +192,11 @@
           }
         }));
     return initializeEntryWithItem(item).then(() => {
-      // TODO(joonbug): Localize the test.
-      assertEquals(getNameText(), 'kCharge');
+      assertEquals(
+          getNameText(),
+          loadTimeData.getStringF(
+              'routineNameText',
+              loadTimeData.getString('batteryChargeRoutineText')));
 
       // Status should show the passed result.
       assertEquals(getStatusBadge().value, 'SUCCESS');
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
index 446ab7d..d1235e1b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
@@ -11,6 +11,7 @@
 import {setSystemRoutineControllerForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 import {ExecutionProgress} from 'chrome://diagnostics/routine_list_executor.js';
 import {BadgeType} from 'chrome://diagnostics/text_badge.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.m.js';
@@ -340,7 +341,9 @@
 
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
-          dx_utils.assertElementContainsText(getStatusTextElement(), 'kMemory');
+          dx_utils.assertElementContainsText(
+              getStatusTextElement(),
+              loadTimeData.getString('memoryRoutineText'));
 
           // Resolve the running test.
           return routineController.resolveRoutineForTesting();
@@ -389,7 +392,8 @@
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
           dx_utils.assertElementContainsText(
-              getStatusTextElement(), 'kFloatingPoint');
+              getStatusTextElement(),
+              loadTimeData.getString('cpuFloatingPointAccuracyRoutineText'));
 
           // Resolve the running test.
           return routineController.resolveRoutineForTesting();
@@ -407,7 +411,8 @@
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
           dx_utils.assertElementContainsText(
-              getStatusTextElement(), 'kCpuCache');
+              getStatusTextElement(),
+              loadTimeData.getString('cpuCacheRoutineText'));
 
           // Resolve the running test.
           return routineController.resolveRoutineForTesting();
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
index b1fa477..1a9ee351 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
@@ -168,7 +168,7 @@
    * @return {!Promise}
    */
   simulateScanComplete(success) {
-    this.scanJobObserverRemote_.onScanComplete(success);
+    this.scanJobObserverRemote_.onScanComplete(success, {'path': ''});
     return flushTasks();
   }
 
diff --git a/chrome/test/data/webui/nearby_share/shared/fake_nearby_contact_manager.js b/chrome/test/data/webui/nearby_share/shared/fake_nearby_contact_manager.js
index 8dd5001..632d01b 100644
--- a/chrome/test/data/webui/nearby_share/shared/fake_nearby_contact_manager.js
+++ b/chrome/test/data/webui/nearby_share/shared/fake_nearby_contact_manager.js
@@ -17,6 +17,8 @@
       this.contactRecords = null;
       /** @private {!Array<!string>} */
       this.allowedContacts_ = [];
+      /** @private {number} */
+      this.numUnreachable_ = 3;
       /** @private {?nearbyShare.mojom.DownloadContactsObserverInterface} */
       this.observer_;
       /** @private {Object} */
@@ -45,6 +47,13 @@
       this.allowedContacts_ = allowedContacts;
     }
 
+    /**
+     * @param {number} numUnreachable
+     */
+    setNumUnreachable(numUnreachable) {
+      this.numUnreachable_ = numUnreachable;
+    }
+
     setupContactRecords() {
       this.contactRecords = [
         {
@@ -74,7 +83,7 @@
     completeDownload() {
       this.observer_.onContactsDownloaded(
           this.allowedContacts_, this.contactRecords || [],
-          /*num_unreachable_contacts_filtered_out=*/ 3);
+          /*num_unreachable_contacts_filtered_out=*/ this.numUnreachable_);
     }
   }
   // #cr_define_end
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js b/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
index b8da5b6c..7e562e4 100644
--- a/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
+++ b/chrome/test/data/webui/nearby_share/shared/nearby_contact_visibility_test.js
@@ -93,6 +93,14 @@
   }
 
   /**
+   * @return {boolean} true when the unreachable contacts message is visibile
+   */
+  function isUnreachableMessageVisible() {
+    return test_util.isChildVisible(
+        visibilityElement, '#unreachableMessage', false);
+  }
+
+  /**
    * Checks the state of the contacts toggle button group
    * @param {boolean} all is allContacts checked?
    * @param {boolean} some is someContacts checked?
@@ -229,4 +237,49 @@
         assertFalse(areContactCheckBoxesVisible());
         assertTrue(isNoContactsSectionVisible());
       });
+
+  test(
+      'Unreachable message appears for 1 unreachable contact',
+      async function() {
+        fakeContactManager.setupContactRecords();
+        fakeContactManager.setNumUnreachable(1);
+        fakeContactManager.completeDownload();
+        visibilityElement.set(
+            'settings.visibility', nearbyShare.mojom.Visibility.kAllContacts);
+
+        // need to wait for the next render to see results
+        await test_util.waitAfterNextRender(visibilityElement);
+
+        assertTrue(isUnreachableMessageVisible());
+      });
+
+  test(
+      'Unreachable message appears for more than 1 unreachable contact',
+      async function() {
+        fakeContactManager.setupContactRecords();
+        fakeContactManager.setNumUnreachable(3);
+        fakeContactManager.completeDownload();
+        visibilityElement.set(
+            'settings.visibility', nearbyShare.mojom.Visibility.kAllContacts);
+
+        // need to wait for the next render to see results
+        await test_util.waitAfterNextRender(visibilityElement);
+
+        assertTrue(isUnreachableMessageVisible());
+      });
+
+  test(
+      'Unreachable message hidden for 0 unreachable contacts',
+      async function() {
+        fakeContactManager.setupContactRecords();
+        fakeContactManager.setNumUnreachable(0);
+        fakeContactManager.completeDownload();
+        visibilityElement.set(
+            'settings.visibility', nearbyShare.mojom.Visibility.kAllContacts);
+
+        // need to wait for the next render to see results
+        await test_util.waitAfterNextRender(visibilityElement);
+
+        assertFalse(isUnreachableMessageVisible());
+      });
 });
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 8c57ea2..6a4e707 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -412,6 +412,8 @@
         "ui/aura/accessibility/ax_tree_source_aura.cc",
         "ui/aura/accessibility/ax_tree_source_aura.h",
       ]
+
+      deps += [ "//build:chromeos_buildflags" ]
     }
 
     deps += [
diff --git a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
index bd3dd17..3a669c40 100644
--- a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chromecast/browser/accessibility/accessibility_manager.h"
 #include "chromecast/browser/cast_browser_process.h"
 #include "ui/accessibility/aura/aura_window_properties.h"
@@ -156,7 +157,7 @@
   } else {
     current_tree_serializer_ =
         std::make_unique<AuraAXTreeSerializer>(current_tree_.get());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     ash::Shell* shell = ash::Shell::Get();
     // Windows within the overlay container get moved to the new monitor when
     // the primary display gets swapped.
@@ -164,7 +165,7 @@
         shell->GetContainer(shell->GetPrimaryRootWindow(),
                             ash::kShellWindowId_OverlayContainer),
         views::AXAuraObjCache::GetInstance());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 }
 
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 95abe526..b0baf6b 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -289,26 +289,19 @@
       "ui.ChromeCrashNotLoggedInDirect.breakpad",
       "ui.ChromeCrashLoggedInDirect.breakpad",
 
-      # TODO(sidereal, crbug.com/1128743, crbug.com/1148527) Remove
-      # _artifact versions of crostini tests from this list once
-      # CL:2374267 has been pulled into the LKGM
-
       # crbug.com/1073084
-      "crostini.CopyPaste.wayland_to_x11_artifact",
       "crostini.CopyPaste.wayland_to_x11_stretch_amd64_stable",
       "crostini.CopyPaste.wayland_to_x11_stretch_arm_stable",
       "crostini.CopyPaste.wayland_to_x11_buster_amd64_stable",
       "crostini.CopyPaste.wayland_to_x11_buster_arm_stable",
 
       # crbug.com/1114654
-      "crostini.Restart.artifact",
       "crostini.Restart.stretch_amd64_stable",
       "crostini.Restart.stretch_arm_stable",
       "crostini.Restart.buster_amd64_stable",
       "crostini.Restart.buster_arm_stable",
 
       # crbug.com/1141944
-      "crostini.LaunchBrowser.artifact",
       "crostini.LaunchBrowser.stretch_amd64_stable",
       "crostini.LaunchBrowser.stretch_arm_stable",
       "crostini.LaunchBrowser.buster_amd64_stable",
@@ -331,7 +324,6 @@
       "printer.PinPrintLexmark.no_pin",
       "printer.PinPrintLexmark.pin",
 
-
       # crbug.com/1147607
       "inputs.VirtualKeyboardAccessibility.stable",
       "inputs.VirtualKeyboardChangeInput.stable",
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index be52428da..5176da6 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -681,6 +681,30 @@
       <message name="IDS_DIAGNOSTICS_CPU_USAGE_TOOLTIP_TEXT" desc="The tooltip for CPU usage." translateable="true">
         This measures the CPU usage, and is an aggregation of all cores
       </message>
+      <message name="IDS_DIANOSTICS_ROUTINE_NAME_TEXT" desc="The text that informs the user which test is currently running." translateable="true">
+        Running <ph name="TEST_NAME">$1<ex>Charging rate</ex></ph> test...
+      </message>
+      <message name="IDS_DIAGNOSTICS_BATTERY_CHARGE_ROUTINE_TEXT" desc="The text for the battery charge routine." translateable="false">
+        Charging rate
+      </message>
+      <message name="IDS_DIAGNOSTICS_BATTERY_DISCHARGE_ROUTINE_TEXT" desc="The text for the battery discharge routine." translateable="false">
+        Discharging rate
+      </message>
+      <message name="IDS_DIAGNOSTICS_CPU_CACHE_ROUTINE_TEXT" desc="The text for the CPU cache routine." translateable="false">
+        Cache
+      </message>
+      <message name="IDS_DIAGNOSTICS_CPU_STRESS_ROUTINE_TEXT" desc="The text for the CPU stress routine." translateable="false">
+        Stress
+      </message>
+      <message name="IDS_DIAGNOSTICS_CPU_FLOATING_POINT_ACCURACY_ROUTINE_TEXT" desc="The text for the CPU floating point accuracy routine." translateable="false">
+        Floating point accuracy
+      </message>
+      <message name="IDS_DIAGNOSTICS_CPU_PRIME_SEARCH_ROUTINE_TEXT" desc="The text for the CPU prime search routine." translateable="false">
+        Prime search
+      </message>
+      <message name="IDS_DIAGNOSTICS_MEMORY_ROUTINE_TEXT" desc="The text for the memory routine." translateable="false">
+        Memory
+      </message>
 
       <!-- Quick Answers -->
       <message name="IDS_QUICK_ANSWERS_DEFINITION_TITLE_TEXT" desc="The title text format string used for Quick Answers definition result card. The first placeholder contains the source query text and the second placeholder contains the phonetics.">
diff --git a/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_NAME_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_NAME_TEXT.png.sha1
new file mode 100644
index 0000000..abe2642a
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_NAME_TEXT.png.sha1
@@ -0,0 +1 @@
+b60c620e19932ddd5c08fd00bee5da7092d79026
\ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/backend/system_data_provider.cc b/chromeos/components/diagnostics_ui/backend/system_data_provider.cc
index 82d6bb6..5d2ee31c 100644
--- a/chromeos/components/diagnostics_ui/backend/system_data_provider.cc
+++ b/chromeos/components/diagnostics_ui/backend/system_data_provider.cc
@@ -62,6 +62,17 @@
   // If there is more than one physical cpu on the device, use the name of the
   // first CPU.
   out_system_info.cpu_model_name = physical_cpus[0]->model_name.value_or("");
+
+  // Calculate `max_clock_speed_khz` as the average of all logical core clock
+  // speeds until we decide the best way to consume the information in the UI.
+  uint32_t total_max_ghz = 0;
+  for (const auto& logical_cpu_ptr : physical_cpus[0]->logical_cpus) {
+    total_max_ghz += logical_cpu_ptr->max_clock_speed_khz;
+  }
+
+  // Integer division.
+  out_system_info.cpu_max_clock_speed_khz =
+      total_max_ghz / physical_cpus[0]->logical_cpus.size();
 }
 
 void PopulateVersionInfo(const healthd::SystemInfo& system_info,
@@ -185,6 +196,18 @@
       cumulative_total / cpu_info.temperature_channels.size();
 }
 
+void PopulateAverageScaledClockSpeed(const healthd::CpuInfo& cpu_info,
+                                     mojom::CpuUsage& out_cpu_usage) {
+  uint32_t total_scaled_ghz = 0;
+  for (const auto& logical_cpu_ptr : cpu_info.physical_cpus[0]->logical_cpus) {
+    total_scaled_ghz += logical_cpu_ptr->scaling_current_frequency_khz;
+  }
+
+  // Integer division.
+  out_cpu_usage.scaling_current_frequency_khz =
+      total_scaled_ghz / cpu_info.physical_cpus[0]->logical_cpus.size();
+}
+
 }  // namespace
 
 SystemDataProvider::SystemDataProvider() {
@@ -524,6 +547,7 @@
 
   ComputeAndPopulateCpuUsage(*cpu_info, *cpu_usage.get());
   PopulateAverageCpuTemperature(*cpu_info, *cpu_usage.get());
+  PopulateAverageScaledClockSpeed(*cpu_info, *cpu_usage.get());
 
   NotifyCpuUsageObservers(cpu_usage);
 }
diff --git a/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc b/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc
index 307d66d..985f6c8 100644
--- a/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc
+++ b/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc
@@ -61,6 +61,7 @@
                                       const std::string& cpu_model,
                                       uint32_t total_memory_kib,
                                       uint16_t cpu_threads_count,
+                                      uint32_t cpu_max_clock_speed_khz,
                                       bool has_battery,
                                       const std::string& milestone_version) {
   // System info
@@ -82,6 +83,9 @@
   // CPU info
   auto cpu_info = cros_healthd::mojom::CpuInfo::New();
   auto physical_cpu_info = cros_healthd::mojom::PhysicalCpuInfo::New();
+  auto logical_cpu_info = cros_healthd::mojom::LogicalCpuInfo::New();
+  logical_cpu_info->max_clock_speed_khz = cpu_max_clock_speed_khz;
+  physical_cpu_info->logical_cpus.push_back(std::move(logical_cpu_info));
   physical_cpu_info->model_name = cpu_model;
   cpu_info->num_total_threads = cpu_threads_count;
   cpu_info->physical_cpus.emplace_back(std::move(physical_cpu_info));
@@ -221,18 +225,25 @@
                                 /*system_info=*/nullptr);
 }
 
-void SetCrosHealthdCpuResponse(const std::vector<CpuUsageData>& usage_data,
-                               const std::vector<int32_t>& cpu_temps) {
+void SetCrosHealthdCpuResponse(
+    const std::vector<CpuUsageData>& usage_data,
+    const std::vector<int32_t>& cpu_temps,
+    const std::vector<uint32_t>& scaled_cpu_clock_speed) {
   auto cpu_info_ptr = cros_healthd::mojom::CpuInfo::New();
   auto physical_cpu_info_ptr = cros_healthd::mojom::PhysicalCpuInfo::New();
 
-  for (const auto& data : usage_data) {
+  DCHECK_EQ(usage_data.size(), scaled_cpu_clock_speed.size());
+  for (size_t i = 0; i < usage_data.size(); ++i) {
+    const auto& data = usage_data[i];
     auto logical_cpu_info_ptr = cros_healthd::mojom::LogicalCpuInfo::New();
 
     logical_cpu_info_ptr->user_time_user_hz = data.GetUserTime();
     logical_cpu_info_ptr->system_time_user_hz = data.GetSystemTime();
     logical_cpu_info_ptr->idle_time_user_hz = data.GetIdleTime();
 
+    logical_cpu_info_ptr->scaling_current_frequency_khz =
+        scaled_cpu_clock_speed[i];
+
     physical_cpu_info_ptr->logical_cpus.emplace_back(
         std::move(logical_cpu_info_ptr));
   }
@@ -256,14 +267,23 @@
 // entry for each logical cpu.
 void SetCrosHealthdCpuUsageResponse(
     const std::vector<CpuUsageData>& usage_data) {
-  // Use fake temp data since none was supplied.
-  SetCrosHealthdCpuResponse(usage_data, {50});
+  // Use fake temp and scaled clock speed data since none was supplied.
+  const std::vector<uint32_t> scaled_clock_speeds(usage_data.size(), 10000);
+  SetCrosHealthdCpuResponse(usage_data, {50}, scaled_clock_speeds);
 }
 
 void SetCrosHealthdCpuTemperatureResponse(
     const std::vector<int32_t>& cpu_temps) {
-  // Use fake usage_data data since none was supplied.
-  SetCrosHealthdCpuResponse({CpuUsageData(1000, 1000, 1000)}, cpu_temps);
+  // Use fake usage_data and scaled clock speed data since none was supplied.
+  SetCrosHealthdCpuResponse({CpuUsageData(1000, 1000, 1000)}, cpu_temps,
+                            {10000});
+}
+
+void SetCrosHealthdCpuScalingResponse(const std::vector<uint32_t>& cpu_speeds) {
+  // Use fake temp and usage_data data since none was supplied.
+  const std::vector<CpuUsageData> usage_data(cpu_speeds.size(),
+                                             CpuUsageData(1000, 1000, 1000));
+  SetCrosHealthdCpuResponse(usage_data, {50}, cpu_speeds);
 }
 
 bool AreValidPowerTimes(int64_t time_to_full, int64_t time_to_empty) {
@@ -398,6 +418,11 @@
   EXPECT_EQ(expected_average_temp, update->average_cpu_temp_celsius);
 }
 
+void VerifyCpuScalingResult(const mojom::CpuUsagePtr& update,
+                            uint32_t expected_scaled_speed) {
+  EXPECT_EQ(expected_scaled_speed, update->scaling_current_frequency_khz);
+}
+
 }  // namespace
 
 struct FakeBatteryChargeStatusObserver
@@ -482,13 +507,15 @@
   const std::string expected_cpu_model = "cpu_model";
   const uint32_t expected_total_memory_kib = 1234;
   const uint16_t expected_cpu_threads_count = 5678;
+  const uint32_t expected_cpu_max_clock_speed_khz = 91011;
   const bool expected_has_battery = true;
   const std::string expected_milestone_version = "M99";
 
   SetCrosHealthdSystemInfoResponse(
       expected_board_name, expected_marketing_name, expected_cpu_model,
       expected_total_memory_kib, expected_cpu_threads_count,
-      expected_has_battery, expected_milestone_version);
+      expected_cpu_max_clock_speed_khz, expected_has_battery,
+      expected_milestone_version);
 
   base::RunLoop run_loop;
   system_data_provider_->GetSystemInfo(
@@ -499,6 +526,8 @@
         EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name);
         EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib);
         EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count);
+        EXPECT_EQ(expected_cpu_max_clock_speed_khz,
+                  ptr->cpu_max_clock_speed_khz);
         EXPECT_EQ(expected_milestone_version,
                   ptr->version_info->milestone_version);
         EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery);
@@ -514,13 +543,15 @@
   const std::string expected_cpu_model = "cpu_model";
   const uint32_t expected_total_memory_kib = 1234;
   const uint16_t expected_cpu_threads_count = 5678;
+  const uint32_t expected_cpu_max_clock_speed_khz = 91011;
   const bool expected_has_battery = false;
   const std::string expected_milestone_version = "M99";
 
   SetCrosHealthdSystemInfoResponse(
       expected_board_name, expected_marketing_name, expected_cpu_model,
       expected_total_memory_kib, expected_cpu_threads_count,
-      expected_has_battery, expected_milestone_version);
+      expected_cpu_max_clock_speed_khz, expected_has_battery,
+      expected_milestone_version);
 
   base::RunLoop run_loop;
   system_data_provider_->GetSystemInfo(
@@ -531,6 +562,8 @@
         EXPECT_EQ(expected_cpu_model, ptr->cpu_model_name);
         EXPECT_EQ(expected_total_memory_kib, ptr->total_memory_kib);
         EXPECT_EQ(expected_cpu_threads_count, ptr->cpu_threads_count);
+        EXPECT_EQ(expected_cpu_max_clock_speed_khz,
+                  ptr->cpu_max_clock_speed_khz);
         EXPECT_EQ(expected_milestone_version,
                   ptr->version_info->milestone_version);
         EXPECT_EQ(expected_has_battery, ptr->device_capabilities->has_battery);
@@ -857,5 +890,53 @@
                       /*expected_average_temp=*/30);
 }
 
+TEST_F(SystemDataProviderTest, CpuUsageScaledClock) {
+  // Setup Timer
+  auto timer = std::make_unique<base::MockRepeatingTimer>();
+  auto* timer_ptr = timer.get();
+  system_data_provider_->SetCpuUsageTimerForTesting(std::move(timer));
+
+  // Setup initial data
+  uint32_t core_1_speed = 4000;
+  uint32_t core_2_speed = 5000;
+
+  SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
+
+  // Registering as an observer should trigger one update.
+  FakeCpuUsageObserver cpu_usage_observer;
+  system_data_provider_->ObserveCpuUsage(
+      cpu_usage_observer.receiver.BindNewPipeAndPassRemote());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1u, cpu_usage_observer.updates.size());
+  VerifyCpuScalingResult(cpu_usage_observer.updates[0],
+                         /*expected_scaled_speed=*/4500);
+
+  core_1_speed = 2000;
+  core_2_speed = 2000;
+
+  SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
+
+  timer_ptr->Fire();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(2u, cpu_usage_observer.updates.size());
+  VerifyCpuScalingResult(cpu_usage_observer.updates[1],
+                         /*expected_scaled_speed=*/2000);
+
+  core_1_speed = 2000;
+  core_2_speed = 2001;
+
+  SetCrosHealthdCpuScalingResponse({core_1_speed, core_2_speed});
+
+  timer_ptr->Fire();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(3u, cpu_usage_observer.updates.size());
+  // Integer division so `expected_scaled_speed` should still be 2000.
+  VerifyCpuScalingResult(cpu_usage_observer.updates[2],
+                         /*expected_scaled_speed=*/2000);
+}
+
 }  // namespace diagnostics
 }  // namespace chromeos
diff --git a/chromeos/components/diagnostics_ui/diagnostics_ui.cc b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
index 32ecd2f..f479633 100644
--- a/chromeos/components/diagnostics_ui/diagnostics_ui.cc
+++ b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
@@ -34,6 +34,9 @@
 void AddDiagnosticsStrings(content::WebUIDataSource* html_source) {
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
       {"adapterStatus", IDS_DIAGNOSTICS_POWER_LABEL},
+      {"batteryChargeRoutineText", IDS_DIAGNOSTICS_BATTERY_CHARGE_ROUTINE_TEXT},
+      {"batteryDischargeRoutineText",
+       IDS_DIAGNOSTICS_BATTERY_DISCHARGE_ROUTINE_TEXT},
       {"batteryChipText", IDS_DIAGNOSTICS_BATTERY_CHIP_TEXT},
       {"batteryHealthLabel", IDS_DIAGNOSTICS_BATTERY_HEALTH_LABEL},
       {"batteryHealthText", IDS_DIAGNOSTICS_BATTERY_HEALTH_TEXT},
@@ -42,8 +45,14 @@
       {"chargeFullDesign", IDS_DIAGNOSTICS_DESIGNED_FULL_CHARGE_LABEL},
       {"chargeFullNow", IDS_DIAGNOSTICS_NOW_FULL_CHARGE_LABEL},
       {"chargeNow", IDS_DIAGNOSTICS_CHARGE_NOW_LABEL},
+      {"cpuCacheRoutineText", IDS_DIAGNOSTICS_CPU_CACHE_ROUTINE_TEXT},
       {"cpuChipText", IDS_DIAGNOSTICS_CPU_CHIP_TEXT},
+      {"cpuFloatingPointAccuracyRoutineText",
+       IDS_DIAGNOSTICS_CPU_FLOATING_POINT_ACCURACY_ROUTINE_TEXT},
+      {"cpuPrimeSearchRoutineText",
+       IDS_DIAGNOSTICS_CPU_PRIME_SEARCH_ROUTINE_TEXT},
       {"cpuSpeedLabel", IDS_DIAGNOSTICS_CPU_SPEED_LABEL},
+      {"cpuStressRoutineText", IDS_DIAGNOSTICS_CPU_STRESS_ROUTINE_TEXT},
       {"cpuTempLabel", IDS_DIAGNOSTICS_CPU_TEMPERATURE_LABEL},
       {"cpuTempText", IDS_DIAGNOSTICS_CPU_TEMPERATURE_TEXT},
       {"cpuTitle", IDS_DIAGNOSTICS_CPU_TITLE},
@@ -61,10 +70,12 @@
       {"diagnosticsTitle", IDS_DIAGNOSTICS_TITLE},
       {"learnMore", IDS_DIANOSTICS_LEARN_MORE_LABEL},
       {"memoryAvailable", IDS_DIAGNOSTICS_MEMORY_AVAILABLE_LABEL},
+      {"memoryRoutineText", IDS_DIAGNOSTICS_MEMORY_ROUTINE_TEXT},
       {"memoryTitle", IDS_DIAGNOSTICS_MEMORY_TITLE},
       {"percentageLabel", IDS_DIAGNOSTICS_PERCENTAGE_LABEL},
       {"powerTime", IDS_DIAGNOSTICS_POWER_TIME_LABEL},
       {"remainingCharge", IDS_DIAGNOSTICS_REMAINING_CHARGE_LABEL},
+      {"routineNameText", IDS_DIANOSTICS_ROUTINE_NAME_TEXT},
       {"sessionLog", IDS_DIAGNOSTICS_SESSION_LOG_LABEL},
       {"totalMemory", IDS_DIAGNOSTICS_TOTAL_MEMORY_LABEL},
       {"usedMemory", IDS_DIAGNOSTICS_USED_MEMORY_LABEL},
diff --git a/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom b/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom
index 9e658a3..d6ea105 100644
--- a/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom
+++ b/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom
@@ -23,6 +23,7 @@
   string cpu_model_name;
   uint32 total_memory_kib;
   uint16 cpu_threads_count;
+  uint32 cpu_max_clock_speed_khz;
   VersionInfo version_info;
   DeviceCapabilities device_capabilities;
 };
@@ -76,6 +77,7 @@
   uint8 percent_usage_system;
   uint8 percent_usage_free;
   uint16 average_cpu_temp_celsius;
+  uint32 scaling_current_frequency_khz;
 };
 
 // Implemented by clients that wish to be updated periodically about changes to
diff --git a/chromeos/components/diagnostics_ui/resources/BUILD.gn b/chromeos/components/diagnostics_ui/resources/BUILD.gn
index 29fb9d5c..7d3626f 100644
--- a/chromeos/components/diagnostics_ui/resources/BUILD.gn
+++ b/chromeos/components/diagnostics_ui/resources/BUILD.gn
@@ -164,6 +164,7 @@
 js_library("routine_result_entry") {
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:load_time_data.m",
   ]
 }
 
@@ -179,6 +180,7 @@
     ":mojo_interface_provider",
     ":routine_result_list",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:load_time_data.m",
   ]
 }
 
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html b/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
index 10f908eb..e96da99 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
@@ -10,6 +10,7 @@
       --diagnostics-data-point-subtitle-font-size: 15px;
       --diagnostics-overview-font-size: 13px;
       --diagnostics-chart-label-font-size: 15px;
+      --diagnostics-chart-tick-font-size: 12px;
 
       --diagnostics-default-font-weight: 500;
       --diagnostics-header-font-weight: 600;
@@ -54,6 +55,10 @@
           font-family: var(--diagnostics-default-font-family);
           font-size: var(--diagnostics-chart-label-font-size);
       };
+      --diagnostics-chart-tick-font: {
+          font-family: var(--diagnostics-header-font-family);
+          font-size: var(--diagnostics-chart-tick-font-size);
+      };
     }
   </style>
 </template>
\ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_types.js b/chromeos/components/diagnostics_ui/resources/diagnostics_types.js
index c2a6c30..0eb58bce 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_types.js
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_types.js
@@ -110,9 +110,8 @@
   kFloatingPoint: 2,
   kPrimeSearch: 3,
   kMemory: 4,
-  kPower: 5,
-  kCharge: 6,
-  kDischarge: 7,
+  kCharge: 5,
+  kDischarge: 6,
 };
 
 /**
diff --git a/chromeos/components/diagnostics_ui/resources/fake_data.js b/chromeos/components/diagnostics_ui/resources/fake_data.js
index c728a67..39a26f7 100644
--- a/chromeos/components/diagnostics_ui/resources/fake_data.js
+++ b/chromeos/components/diagnostics_ui/resources/fake_data.js
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryRateRoutineResult, CpuUsage, ExternalPowerSource, MemoryUsage, RoutineName, StandardRoutineResult, SystemInfo} from './diagnostics_types.js'
-import {stringToMojoString16} from './mojo_utils.js';
+import { BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryRateRoutineResult, CpuUsage, ExternalPowerSource, MemoryUsage, RoutineName, StandardRoutineResult, SystemInfo } from './diagnostics_types.js'
+import { stringToMojoString16 } from './mojo_utils.js';
 
 /** @type {!Array<!BatteryChargeStatus>} */
 export const fakeBatteryChargeStatus = [
@@ -128,10 +128,11 @@
   boardName: 'CrOS Board',
   cpuModelName: 'BestCpu SoFast 1000',
   cpuThreadsCount: 8,
-  deviceCapabilities: {hasBattery: true},
+  cpuMaxClockSpeedKhz: 1000,
+  deviceCapabilities: { hasBattery: true },
   marketingName: 'Coolest Chromebook',
   totalMemoryKib: 128000,
-  versionInfo: {milestoneVersion: 'M99'},
+  versionInfo: { milestoneVersion: 'M99' },
 };
 
 /** @type {!SystemInfo} */
@@ -139,10 +140,11 @@
   boardName: 'CrOS Board',
   cpuModelName: 'BestCpu SoFast 1000',
   cpuThreadsCount: 8,
-  deviceCapabilities: {hasBattery: false},
+  cpuMaxClockSpeedKhz: 1000,
+  deviceCapabilities: { hasBattery: false },
   marketingName: 'Coolest Chromebook',
   totalMemoryKib: 128000,
-  versionInfo: {milestoneVersion: 'M99'},
+  versionInfo: { milestoneVersion: 'M99' },
 };
 
 /** @type {!Map<!RoutineName, !StandardRoutineResult>} */
@@ -172,4 +174,4 @@
       time_delta_seconds: 0
     }
   ],
-]);
\ No newline at end of file
+]);
diff --git a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.html b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.html
index c0b1a67..f3e70f1f 100644
--- a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.html
+++ b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.html
@@ -1,10 +1,24 @@
 <style include="diagnostics-shared diagnostics-fonts">
-  .grid line {
-    stroke: lightgrey;
-    stroke-opacity: 0.7;
+  g.tick line {
+    stroke: var(--google-grey-200);
+    stroke-width: 1px;
     shape-rendering: crispEdges;
   }
 
+  g.tick:first-of-type line {
+    stroke: var(--google-grey-700);
+  }
+
+  g.tick text {
+    color: var(--google-grey-700);
+    line-height: 18px;
+    @apply --diagnostics-chart-tick-font;
+  }
+
+  path.domain {
+    visibility: hidden;
+  }
+
   #chart-legend {
     text-align: center;
   }
@@ -23,23 +37,49 @@
     stroke-width: 1.5px;
   }
 
-  /* TODO(joonbug): Update with real colors as vars */
   .user-area {
-    fill: orange;
+    fill: url(#user-gradient);
+    shape-render: optimizeSpeed;
+    stroke-width: 1.5px;
+    stroke: var(--google-blue-600);
   }
 
   .system-area {
-    fill: blue;
+    fill: url(#system-gradient);
+    shape-render: optimizeSpeed;
+    stroke-width: 1.5px;
+    stroke: var(--google-yellow-600);
+  }
+
+  .gradient-blue {
+    stop-color: var(--google-blue-300);
+  }
+
+  .gradient-yellow {
+    stop-color: var(--google-yellow-300);
+  }
+
+  .gradient-opacity {
+    stop-opacity: 0;
   }
 </style>
 
 <svg id="chart" width$="[[width_]]" height$="[[height_]]">
   <g id="chartGroup">
-    <!-- Define chart area and boundaries -->
     <defs>
+      <!-- Define chart area and boundaries -->
       <clipPath id="defClip">
         <rect width$="[[graphWidth_]]" height$="[[graphHeight_]]"></rect>
       </clipPath>
+      <!-- Chart area gradient -->
+      <linearGradient id="user-gradient" gradientTransform="rotate(90)">
+        <stop offset="0%" class="gradient-blue"></stop>
+        <stop offset="100%" class="gradient-blue gradient-opacity"></stop>
+      </linearGradient>
+      <linearGradient id="system-gradient" gradientTransform="rotate(90)">
+        <stop offset="0%" class="gradient-yellow"></stop>
+        <stop offset="100%" class="gradient-yellow gradient-opacity"></stop>
+      </linearGradient>
     </defs>
 
     <g id="gridLines" class="grid"></g>
diff --git a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
index 8b5bd3d..249f9e70 100644
--- a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
+++ b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
@@ -108,33 +108,33 @@
     /** @private {number} */
     width_: {
       type: Number,
-      value: 550,
+      value: 560,
     },
 
     /** @private {number} */
     height_: {
       type: Number,
-      value: 100,
+      value: 114,
     },
 
     /** @private {!Object} */
-    margin_: {
+    padding_: {
       type: Object,
-      value: {top: 10, right: 20, bottom: 10, left: 30},
+      value: {top: 10, right: 20, bottom: 10, left: 50, tick: 10},
     },
 
     /** @private {number} */
     graphWidth_: {
       readOnly: true,
       type: Number,
-      computed: 'getGraphDimension_(width_, margin_.left, margin_.right)'
+      computed: 'getGraphDimension_(width_, padding_.left, padding_.right)'
     },
 
     /** @private {number} */
     graphHeight_: {
       readOnly: true,
       type: Number,
-      computed: 'getGraphDimension_(height_, margin_.top, margin_.bottom)'
+      computed: 'getGraphDimension_(height_, padding_.top, padding_.bottom)'
     }
   },
 
@@ -202,7 +202,7 @@
     // Position chartGroup inside the margin.
     chartGroup.attr(
         'transform',
-        'translate(' + this.margin_.left + ',' + this.margin_.top + ')');
+        'translate(' + this.padding_.left + ',' + this.padding_.top + ')');
 
     // Draw the y-axis legend and also draw the horizontal gridlines by
     // reversing the ticks back into the chart body.
@@ -211,6 +211,7 @@
             d3.axisLeft(/** @type {!d3.LinearScale} */ (this.yAxisScaleFn_))
                 .tickValues(this.yAxisTicks_)
                 .tickFormat((y) => this.getPercentageLabel_(y))
+                .tickPadding(this.padding_.tick)
                 .tickSize(-this.graphWidth_)  // Extend the ticks into the
                                               // entire graph as gridlines.
         );
@@ -247,9 +248,10 @@
         .area()
         // Take the index of each data as x values.
         .x((data, i) => this.xAxisScaleFn_(i))
-        // Bottom coordinates of each area.
+        // Bottom coordinates of each area. System area extends down to -1
+        // instead of 0 to avoid the area border from showing up.
         .y0(data => this.yAxisScaleFn_(
-                areaClass === 'system-area' ? 0 : data.system))
+                areaClass === 'system-area' ? -1 : data.system))
         // Top coordinates of each area.
         .y1(data => this.yAxisScaleFn_(
                 areaClass === 'system-area' ? data.system :
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
index ce14462c..a0791ec 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
@@ -7,30 +7,38 @@
 import './text_badge.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {RoutineName, RoutineResult, StandardRoutineResult} from './diagnostics_types.js';
 import {ExecutionProgress, ResultStatusItem} from './routine_list_executor.js';
 import {BadgeType} from './text_badge.js';
 
 /**
- * Resolves an enum value to the string name. This is used temporarily to
- * provide a human readable string until the final mapping of enum values to
- * localized strings is finalized.
- * TODO(zentaro): Remove this function when strings are finalized.
- * @param {!Object} enumType
- * @param {number} enumValue
+ * Resolves a routine name to its corresponding localized string name.
+ * @param {!RoutineName} routineName
  * @return {string}
  */
-export function lookupEnumValueName(enumType, enumValue) {
-  for (const [key, value] of Object.entries(enumType)) {
-    if (value === enumValue) {
-      return key;
-    }
+export function getRoutineName(routineName) {
+  switch (routineName) {
+    case RoutineName.kCharge:
+      return loadTimeData.getString('batteryChargeRoutineText');
+    case RoutineName.kDischarge:
+      return loadTimeData.getString('batteryDischargeRoutineText');
+    case RoutineName.kCpuCache:
+      return loadTimeData.getString('cpuCacheRoutineText');
+    case RoutineName.kCpuStress:
+      return loadTimeData.getString('cpuStressRoutineText');
+    case RoutineName.kFloatingPoint:
+      return loadTimeData.getString('cpuFloatingPointAccuracyRoutineText');
+    case RoutineName.kPrimeSearch:
+      return loadTimeData.getString('cpuPrimeSearchRoutineText');
+    case RoutineName.kMemory:
+      return loadTimeData.getString('memoryRoutineText');
+    default:
+      // Values should always be found in the enum.
+      assert(false);
+      return '';
   }
-
-  // Values should always be found in the enum.
-  assert(false);
-  return '';
 }
 
 /**
@@ -51,21 +59,17 @@
     /** @private */
     routineName_: {
       type: String,
-      computed: 'getRoutineName_(item.routine)',
+      computed: 'getRunningRoutineString_(item.routine)',
     },
   },
-
   /**
-   * Get the string name for the routine.
-   * TODO(zentaro): Replace with a mapping to localized string when they are
-   * finalized.
+   * Get the localized string name for the routine.
    * @param {!RoutineName} routine
    * @return {string}
    */
-  getRoutineName_(routine) {
-    return lookupEnumValueName(RoutineName, routine);
+  getRunningRoutineString_(routine) {
+    return loadTimeData.getStringF('routineNameText', getRoutineName(routine));
   },
-
   /**
    * @param {!RoutineResult} result
    * @return {!StandardRoutineResult}
diff --git a/chromeos/components/diagnostics_ui/resources/routine_section.js b/chromeos/components/diagnostics_ui/resources/routine_section.js
index 10947c49..008a0bbf 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_section.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_section.js
@@ -10,12 +10,13 @@
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {RoutineName, StandardRoutineResult, SystemRoutineControllerInterface} from './diagnostics_types.js';
 import {getSystemRoutineController} from './mojo_interface_provider.js';
 import {ExecutionProgress, RoutineListExecutor} from './routine_list_executor.js';
-import {lookupEnumValueName} from './routine_result_entry.js';
+import {getRoutineName} from './routine_result_entry.js';
 import {BadgeType} from './text_badge.js';
 
 /**
@@ -111,10 +112,8 @@
           .runRoutines(
               filteredRoutines,
               (status) => {
-                // TODO(joonbug): Update this function to use localized test
-                // name
-                this.currentTestName_ =
-                    lookupEnumValueName(RoutineName, status.routine);
+                this.currentTestName_ = loadTimeData.getStringF(
+                    'routineNameText', getRoutineName(status.routine));
 
                 if (status.result &&
                     status.result.simpleResult !==
@@ -177,9 +176,8 @@
 
   /** @protected */
   getTextStatus_() {
-    // TODO(joonbug): Localize this string.
     if (this.executionStatus_ === ExecutionProgress.kRunning) {
-      return `Running ${this.currentTestName_} test`;
+      return this.currentTestName_;
     }
     return this.hasTestFailure_ ? 'Test failed' : 'Test succeeded';
   },
diff --git a/chromeos/components/help_app_ui/help_app_ui.cc b/chromeos/components/help_app_ui/help_app_ui.cc
index 68db7c6..2214793 100644
--- a/chromeos/components/help_app_ui/help_app_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_ui.cc
@@ -80,6 +80,10 @@
                             ContentSettingsType::JAVASCRIPT,
                             ContentSettingsType::SOUND,
                         });
+
+  // JavaScript errors are reported via CrashReportPrivate.reportError. Don't
+  // send duplicate reports via WebUI.
+  web_ui->DisableJavaScriptErrorReporting();
 }
 
 HelpAppUI::~HelpAppUI() = default;
diff --git a/chromeos/components/media_app_ui/media_app_ui.cc b/chromeos/components/media_app_ui/media_app_ui.cc
index 5e4e2d01a..5aa892f 100644
--- a/chromeos/components/media_app_ui/media_app_ui.cc
+++ b/chromeos/components/media_app_ui/media_app_ui.cc
@@ -96,6 +96,10 @@
 
   // Add ability to request chrome-untrusted: URLs.
   web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
+
+  // JavaScript errors are reported via CrashReportPrivate.reportError. Don't
+  // send duplicate reports via WebUI.
+  web_ui->DisableJavaScriptErrorReporting();
 }
 
 MediaAppUI::~MediaAppUI() = default;
diff --git a/chromeos/components/scanning/mojom/scanning.mojom b/chromeos/components/scanning/mojom/scanning.mojom
index 153b591..650774a 100644
--- a/chromeos/components/scanning/mojom/scanning.mojom
+++ b/chromeos/components/scanning/mojom/scanning.mojom
@@ -103,8 +103,9 @@
   OnPageComplete(array<uint8> page_data);
 
   // Called when the scan is complete. |success| indicates whether the scan
-  // completed successfully.
-  OnScanComplete(bool success);
+  // completed successfully. |last_scanned_file_path| is the file path of
+  // the last page scanned in a scan job.
+  OnScanComplete(bool success, mojo_base.mojom.FilePath last_scanned_file_path);
 
   // Called when canceling the current scan job is complete. |success|
   // indicates whether the scan job was cancelled successfully.
diff --git a/chromeos/components/scanning/resources/scanning_app.js b/chromeos/components/scanning/resources/scanning_app.js
index 03688de..50208a7f 100644
--- a/chromeos/components/scanning/resources/scanning_app.js
+++ b/chromeos/components/scanning/resources/scanning_app.js
@@ -171,6 +171,13 @@
       type: Boolean,
       value: false,
     },
+
+    /**
+     * The file path of the last scanned page of a successful scan job. Used to
+     * open the Files app with the correct file highlighted.
+     * @private {?mojoBase.mojom.FilePath}
+     */
+    lastScannedFilePath_: Object,
   },
 
   /** @override */
@@ -228,9 +235,11 @@
   /**
    * Overrides chromeos.scanning.mojom.ScanJobObserverInterface.
    * @param {boolean} success
+   * @param {!mojoBase.mojom.FilePath} lastScannedFilePath
    */
-  onScanComplete(success) {
+  onScanComplete(success, lastScannedFilePath) {
     if (success) {
+      this.lastScannedFilePath_ = lastScannedFilePath;
       this.setAppState_(AppState.DONE);
       return;
     }
diff --git a/chromeos/dbus/dlcservice/dlcservice_client.cc b/chromeos/dbus/dlcservice/dlcservice_client.cc
index 8614270..429226e 100644
--- a/chromeos/dbus/dlcservice/dlcservice_client.cc
+++ b/chromeos/dbus/dlcservice/dlcservice_client.cc
@@ -356,10 +356,11 @@
                  ProgressCallback progress_callback,
                  dbus::Response* response,
                  dbus::ErrorResponse* err_response) {
-    HoldInstallation(dlc_id, std::move(install_callback),
-                     std::move(progress_callback));
-    if (response)
+    if (response) {
+      HoldInstallation(dlc_id, std::move(install_callback),
+                       std::move(progress_callback));
       return;
+    }
 
     const auto err = DlcserviceErrorResponseHandler(err_response).get_err();
     if (err == dlcservice::kErrorBusy) {
@@ -367,6 +368,8 @@
           &DlcserviceClientImpl::Install, weak_ptr_factory_.GetWeakPtr(),
           dlc_id, std::move(install_callback), std::move(progress_callback)));
     } else {
+      HoldInstallation(dlc_id, std::move(install_callback),
+                       std::move(progress_callback));
       dlcservice::DlcState dlc_state;
       dlc_state.set_id(dlc_id);
       dlc_state.set_last_error_code(err);
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc
index d1cfacb..6dff89b4 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -694,11 +694,11 @@
 void FakeSessionManagerClient::QueryAdbSideload(
     QueryAdbSideloadCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback),
-                     adb_sideload_enabled_ ? AdbSideloadResponseCode::SUCCESS
-                                           : AdbSideloadResponseCode::FAILED,
-                     adb_sideload_enabled_));
+      FROM_HERE, base::BindOnce(std::move(callback),
+                                force_query_adb_sideload_failure_
+                                    ? AdbSideloadResponseCode::FAILED
+                                    : AdbSideloadResponseCode::SUCCESS,
+                                adb_sideload_enabled_));
 }
 
 void FakeSessionManagerClient::NotifyArcInstanceStopped() {
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h
index 222b5b6..05a4284 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -264,6 +264,10 @@
     adb_sideload_enabled_ = adb_sideload_enabled;
   }
 
+  void set_force_query_adb_sideload_failure(bool force_failure) {
+    force_query_adb_sideload_failure_ = force_failure;
+  }
+
   bool session_stopped() const { return session_stopped_; }
 
   const SessionManagerClient::ActiveSessionsMap& user_sessions() const {
@@ -301,10 +305,14 @@
   // If set to true, StorePolicy() always fails.
   bool force_store_policy_failure_ = false;
 
-  // It set to true, RetrievePolicy() always succeeds with an empty policy blob.
+  // If set to true, RetrievePolicy() always succeeds with an empty policy blob.
   // This simulates a policy load error in session manager.
   bool force_retrieve_policy_load_error_ = false;
 
+  // If set to true, QueryAdbSideload() always replies with a failed
+  // response, irrespective of the value of adb_sideload_enabled_.
+  bool force_query_adb_sideload_failure_ = false;
+
   int clear_forced_re_enrollment_vpd_call_count_ = 0;
   // Callback which is run after calling |StartDeviceWipe| or
   // |StartRemoteDeviceWipe|.
diff --git a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
index c5113b4..52406955 100644
--- a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
+++ b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
@@ -4,9 +4,26 @@
 
 #include "chromeos/dbus/tpm_manager/fake_tpm_manager_client.h"
 
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
 #include "base/notreached.h"
+#include "base/threading/thread_task_runner_handle.h"
 
 namespace chromeos {
+namespace {
+
+// Posts `callback` on the current thread's task runner, passing it the
+// `reply` message.
+template <class ReplyType>
+void PostProtoResponse(base::OnceCallback<void(const ReplyType&)> callback,
+                       const ReplyType& reply) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), reply));
+}
+
+}  // namespace
 
 FakeTpmManagerClient::FakeTpmManagerClient() = default;
 
@@ -21,7 +38,7 @@
 void FakeTpmManagerClient::GetVersionInfo(
     const ::tpm_manager::GetVersionInfoRequest& request,
     GetVersionInfoCallback callback) {
-  NOTIMPLEMENTED();
+  PostProtoResponse(std::move(callback), version_info_reply_);
 }
 
 void FakeTpmManagerClient::GetDictionaryAttackInfo(
@@ -42,4 +59,13 @@
   NOTIMPLEMENTED();
 }
 
+TpmManagerClient::TestInterface* FakeTpmManagerClient::GetTestInterface() {
+  return this;
+}
+
+::tpm_manager::GetVersionInfoReply*
+FakeTpmManagerClient::mutable_version_info_reply() {
+  return &version_info_reply_;
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
index 33b656f..77371de9a 100644
--- a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
+++ b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
@@ -13,7 +13,8 @@
 namespace chromeos {
 
 class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
-    : public TpmManagerClient {
+    : public TpmManagerClient,
+      public TpmManagerClient::TestInterface {
  public:
   FakeTpmManagerClient();
   ~FakeTpmManagerClient() override;
@@ -38,6 +39,14 @@
   void ClearStoredOwnerPassword(
       const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
       ClearStoredOwnerPasswordCallback callback) override;
+
+  TpmManagerClient::TestInterface* GetTestInterface() override;
+
+  // TpmManagerClient::TestInterface:
+  ::tpm_manager::GetVersionInfoReply* mutable_version_info_reply() override;
+
+ private:
+  ::tpm_manager::GetVersionInfoReply version_info_reply_;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/tpm_manager/tpm_manager_client.cc b/chromeos/dbus/tpm_manager/tpm_manager_client.cc
index 85b7dd01..556b44d4 100644
--- a/chromeos/dbus/tpm_manager/tpm_manager_client.cc
+++ b/chromeos/dbus/tpm_manager/tpm_manager_client.cc
@@ -103,6 +103,8 @@
   }
 
  private:
+  TestInterface* GetTestInterface() override { return nullptr; }
+
   // Calls tpm_managerd's |method_name| method, passing in |request| as input
   // with |timeout_ms|. Once the (asynchronous) call finishes, |callback| is
   // called with the response proto.
diff --git a/chromeos/dbus/tpm_manager/tpm_manager_client.h b/chromeos/dbus/tpm_manager/tpm_manager_client.h
index a93b86d..52ed359 100644
--- a/chromeos/dbus/tpm_manager/tpm_manager_client.h
+++ b/chromeos/dbus/tpm_manager/tpm_manager_client.h
@@ -34,6 +34,15 @@
   using ClearStoredOwnerPasswordCallback = base::OnceCallback<void(
       const ::tpm_manager::ClearStoredOwnerPasswordReply&)>;
 
+  // Interface with testing functionality. Accessed through GetTestInterface(),
+  // only implemented in the fake implementation.
+  class TestInterface {
+   public:
+    // Gets a mutable reply that is returned when `GetVersionInfo()` is called.
+    virtual ::tpm_manager::GetVersionInfoReply*
+    mutable_version_info_reply() = 0;
+  };
+
   // Not copyable or movable.
   TpmManagerClient(const TpmManagerClient&) = delete;
   TpmManagerClient& operator=(const TpmManagerClient&) = delete;
@@ -80,6 +89,9 @@
       const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
       ClearStoredOwnerPasswordCallback callback) = 0;
 
+  // Returns an interface for testing (fake only), or returns nullptr.
+  virtual TestInterface* GetTestInterface() = 0;
+
  protected:
   // Initialize/Shutdown should be used instead.
   TpmManagerClient();
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index 775fa45f..88ac294c 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-89-4324.9-1606128713-benchmark-89.0.4334.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-89-4324.9-1606128713-benchmark-89.0.4335.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 2606383d..f333af2f 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-89-4324.9-1606129869-benchmark-89.0.4334.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-89-4324.9-1606129869-benchmark-89.0.4335.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/tts/google_tts_stream.cc b/chromeos/services/tts/google_tts_stream.cc
index 1870133d..8d2d38d0 100644
--- a/chromeos/services/tts/google_tts_stream.cc
+++ b/chromeos/services/tts/google_tts_stream.cc
@@ -140,8 +140,9 @@
   TtsService::AudioBuffer buf;
   buf.frames.resize(libchrometts_.GoogleTtsGetFramesInAudioBuffer());
   size_t frames_in_buf = 0;
-  buf.status =
+  const int status =
       libchrometts_.GoogleTtsReadBuffered(&buf.frames[0], &frames_in_buf);
+  buf.status = status;
 
   buf.frames.resize(frames_in_buf);
 
@@ -153,7 +154,7 @@
 
   owner_->AddAudioBuffer(std::move(buf));
 
-  if (buf.status <= 0)
+  if (status <= 0)
     return;
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromeos/tpm/install_attributes.cc b/chromeos/tpm/install_attributes.cc
index e02c20d..781ccef54 100644
--- a/chromeos/tpm/install_attributes.cc
+++ b/chromeos/tpm/install_attributes.cc
@@ -297,8 +297,7 @@
   }
 
   // Clearing the TPM password seems to be always a good deal.
-  if (tpm_util::TpmIsEnabled() && !tpm_util::TpmIsBeingOwned() &&
-      tpm_util::TpmIsOwned()) {
+  if (tpm_util::TpmIsEnabled() && tpm_util::TpmIsOwned()) {
     cryptohome_client_->CallTpmClearStoredPasswordAndBlock();
   }
 
diff --git a/components/arc/session/arc_upgrade_params.h b/components/arc/session/arc_upgrade_params.h
index 39b7890..defd02c 100644
--- a/components/arc/session/arc_upgrade_params.h
+++ b/components/arc/session/arc_upgrade_params.h
@@ -52,6 +52,10 @@
   // managed.
   bool is_managed_adb_sideloading_allowed = false;
 
+  // Whether adb sideloading is enabled or not.
+  // This parameter is used only for ARCVM.
+  bool is_adb_sideloading_enabled = false;
+
   // Option to disable ACTION_BOOT_COMPLETED broadcast for 3rd party apps.
   // The constructor automatically populates this from command-line.
   bool skip_boot_completed_broadcast;
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/components/arc/session/arc_vm_client_adapter.cc
index c80e0ec9..a450805 100644
--- a/components/arc/session/arc_vm_client_adapter.cc
+++ b/components/arc/session/arc_vm_client_adapter.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
@@ -46,6 +47,7 @@
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/arc/arc_features.h"
@@ -717,6 +719,32 @@
         JobDesc{kArcVmPostLoginServicesJobName, UpstartOperation::JOB_START,
                 std::move(environment)},
     };
+
+    VLOG(2) << "Checking adb sideload status";
+    chromeos::SessionManagerClient::Get()->QueryAdbSideload(base::BindOnce(
+        &ArcVmClientAdapter::OnCallQueryAdbSideloadAllowed,
+        weak_factory_.GetWeakPtr(), std::move(params), std::move(jobs),
+        std::move(file_system_status), std::move(callback)));
+  }
+
+  void OnCallQueryAdbSideloadAllowed(
+      UpgradeParams params,
+      std::deque<JobDesc> jobs,
+      FileSystemStatus file_system_status,
+      chromeos::VoidDBusMethodCallback callback,
+      chromeos::SessionManagerClient::AdbSideloadResponseCode response_code,
+      bool enabled) {
+    VLOG(1) << "IsAdbSideloadAllowed, response_code="
+            << static_cast<int>(response_code) << ", enabled=" << enabled;
+
+    if (response_code !=
+        chromeos::SessionManagerClient::AdbSideloadResponseCode::SUCCESS) {
+      LOG(ERROR) << "Unsuccessful response from QueryAdbSideload";
+      std::move(callback).Run(false);
+      return;
+    }
+    params.is_adb_sideloading_enabled = enabled;
+
     ConfigureUpstartJobs(
         std::move(jobs),
         base::BindOnce(&ArcVmClientAdapter::OnConfigureUpstartJobsOnUpgradeArc,
@@ -909,6 +937,8 @@
   std::vector<std::string> result = {
       base::StringPrintf("%s.disable_boot_completed=%d", prefix.c_str(),
                          upgrade_params.skip_boot_completed_broadcast),
+      base::StringPrintf("%s.enable_adb_sideloading=%d", prefix.c_str(),
+                         upgrade_params.is_adb_sideloading_enabled),
       base::StringPrintf("%s.copy_packages_cache=%d", prefix.c_str(),
                          static_cast<int>(upgrade_params.packages_cache_mode)),
       base::StringPrintf("%s.skip_gms_core_cache=%d", prefix.c_str(),
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc
index e8d01200..be9905d 100644
--- a/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -32,6 +32,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
 #include "components/arc/arc_util.h"
 #include "components/arc/session/arc_session.h"
@@ -270,9 +271,12 @@
         base::TimeDelta::FromMilliseconds(100),
         // connect_sleep_duration_initial
         base::TimeDelta::FromMilliseconds(20));
+
+    chromeos::SessionManagerClient::InitializeFake();
   }
 
   void TearDown() override {
+    chromeos::SessionManagerClient::Shutdown();
     adapter_->RemoveObserver(this);
     adapter_.reset();
     run_loop_.reset();
@@ -817,6 +821,26 @@
   EXPECT_TRUE(arc_instance_stopped_called());
 }
 
+// Tests that an "invalid Adb Sideload response" case is handled properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoValidAdbResponse) {
+  SetValidUserInfo();
+  StartMiniArc();
+
+  // Ask the Fake Session Manager to return a failed Adb Sideload response.
+  chromeos::FakeSessionManagerClient::Get()
+      ->set_force_query_adb_sideload_failure(true);
+  UpgradeArc(false);
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Try to stop the VM. No VM is running so StopVm() shouldn't be called.
+  adapter()->StopArcInstance(/*on_shutdown=*/false,
+                             /*should_backup_log=*/false);
+  run_loop()->Run();
+  EXPECT_FALSE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
 // Tests that "no serial" failure is handled properly.
 TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoSerial) {
   // Don't set the serial number. Note that we cannot call StartArcVm() without
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index df1d12d..1015ea9 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -20,6 +20,7 @@
 #include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/containers/adapters.h"
+#include "base/containers/flat_map.h"
 #include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/guid.h"
@@ -432,9 +433,15 @@
 
 // Returns how many fields with type |field_type| may be filled in a form at
 // maximum.
-int TypeValueFormFillingLimit(ServerFieldType field_type) {
-  return field_type == CREDIT_CARD_NUMBER ? kCreditCardTypeValueFormFillingLimit
-                                          : kTypeValueFormFillingLimit;
+size_t TypeValueFormFillingLimit(ServerFieldType field_type) {
+  switch (field_type) {
+    case CREDIT_CARD_NUMBER:
+      return kCreditCardTypeValueFormFillingLimit;
+    case ADDRESS_HOME_STATE:
+      return kStateTypeValueFormFillingLimit;
+    default:
+      return kTypeValueFormFillingLimit;
+  }
 }
 
 }  // namespace
@@ -1763,7 +1770,8 @@
 
   // Count the number of times the value of a specific type was filled into the
   // form.
-  std::map<ServerFieldType, int> type_filling_count;
+  base::flat_map<ServerFieldType, size_t> type_filling_count;
+  type_filling_count.reserve(form_structure->field_count());
 
   for (size_t i = 0; i < form_structure->field_count(); ++i) {
     std::string field_number = base::StringPrintf("Field %zu", i);
@@ -1853,7 +1861,7 @@
 
     // A field with a specific type is only allowed to be filled a limited
     // number of times given by |TypeValueFormFillingLimit(field_type)|.
-    if (type_filling_count[field_type] >=
+    if (++type_filling_count[field_type] >
         TypeValueFormFillingLimit(field_type)) {
       buffer << Tr{} << field_number
              << "Skipped: field-type filling-limit reached";
@@ -1888,10 +1896,6 @@
     bool has_value_after = !result.fields[i].value.empty();
     bool is_autofilled_after = result.fields[i].is_autofilled;
 
-    // If the field was actually filled, increment the filling counter.
-    if (is_autofilled_after)
-      type_filling_count[field_type]++;
-
     buffer << Tr{} << field_number
            << base::StringPrintf(
                   "Fillable - has value: %d->%d; autofilled: %d->%d. %s",
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 188058d..2cd3b31 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -2936,6 +2936,14 @@
     form.fields.push_back(field);
   }
 
+  // Create a selection box for the state that hat the correct entry to be
+  // filled with user data. Note, TN is the official abbreviation for Tennessee.
+  for (int i = 0; i < 20; ++i) {
+    test::CreateTestSelectField("Country", "country", "", {"DE", "FR", "US"},
+                                {"DE", "FR", "US"}, 3, &field);
+    form.fields.push_back(field);
+  }
+
   std::vector<FormData> forms(1, form);
   FormsSeen(forms);
 
@@ -2972,17 +2980,18 @@
                       response_data.fields[4 + i]);
   }
 
-  // Verify that the next 8 selection boxes are correctly filled again.
-  for (int i = 0; i < 8; i++) {
+  // Verify that the remaining selection boxes are correctly filled again
+  // because there's no limit on filling ADDRESS_HOME_STATE fields.
+  for (int i = 0; i < 20; i++) {
     ExpectFilledField("State", "state", "TN", "select-one",
                       response_data.fields[24 + i]);
   }
 
-  // Verify that the last 12 boxes are not filled because the filling limit for
-  // the state type is already reached.
-  for (int i = 0; i < 12; i++) {
-    ExpectFilledField("State", "state", "", "select-one",
-                      response_data.fields[32 + i]);
+  // Verify that only the first 9 of the remaining selection boxes are
+  // correctly filled due to the limit on filling ADDRESS_HOME_COUNTRY fields.
+  for (int i = 0; i < 20; i++) {
+    ExpectFilledField("Country", "country", i < 9 ? "US" : "", "select-one",
+                      response_data.fields[44 + i]);
   }
 }
 
diff --git a/components/autofill/core/browser/pattern_provider/transpile_default_regex_patterns.py b/components/autofill/core/browser/pattern_provider/transpile_default_regex_patterns.py
index dd1cb76..4bd93d80 100755
--- a/components/autofill/core/browser/pattern_provider/transpile_default_regex_patterns.py
+++ b/components/autofill/core/browser/pattern_provider/transpile_default_regex_patterns.py
@@ -4,7 +4,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-
+import io
 import json
 import sys
 
@@ -54,55 +54,61 @@
   return lines
 
 
-def build_cpp_function(cpp, output):
-  output.write('// Copyright 2020 The Chromium Authors. All rights reserved.\n')
-  output.write('// Use of this source code is governed by a BSD-style license ')
-  output.write('that can be\n')
-  output.write('// found in the LICENSE file.\n')
-  output.write('\n')
-  output.write('#include "components/autofill/core/browser/pattern_provider/'\
+def build_cpp_function(cpp, output_handle):
+  def output(s):
+    # unicode() exists and is necessary only in Python 2, not in Python 3.
+    if sys.version_info[0] < 3:
+      s = unicode(s, 'utf-8')
+    output_handle.write(s)
+
+  output('// Copyright 2020 The Chromium Authors. All rights reserved.\n')
+  output('// Use of this source code is governed by a BSD-style license ')
+  output('that can be\n')
+  output('// found in the LICENSE file.\n')
+  output('\n')
+  output('#include "components/autofill/core/browser/pattern_provider/'\
                'default_regex_patterns.h"\n')
-  output.write('#include "components/autofill/core/common/language_code.h"\n')
-  output.write('\n')
-  output.write('namespace autofill {\n')
-  output.write('\n')
-  output.write('PatternProvider::Map CreateDefaultRegexPatterns() {\n')
-  output.write('  struct JsonPattern {\n')
-  output.write('    const char* name;\n')
-  output.write('    const char* language;\n')
-  output.write('    const char* positive_pattern;\n')
-  output.write('    const char* negative_pattern;\n')
-  output.write('    float positive_score;\n')
-  output.write('    uint8_t match_field_attributes;\n')
-  output.write('    uint16_t match_field_input_types;\n')
-  output.write('  };\n')
-  output.write('\n')
+  output('#include "components/autofill/core/common/language_code.h"\n')
+  output('\n')
+  output('namespace autofill {\n')
+  output('\n')
+  output('PatternProvider::Map CreateDefaultRegexPatterns() {\n')
+  output('  struct JsonPattern {\n')
+  output('    const char* name;\n')
+  output('    const char* language;\n')
+  output('    const char* positive_pattern;\n')
+  output('    const char* negative_pattern;\n')
+  output('    float positive_score;\n')
+  output('    uint8_t match_field_attributes;\n')
+  output('    uint16_t match_field_input_types;\n')
+  output('  };\n')
+  output('\n')
   for line in build_cpp_map_population(cpp):
-    output.write(line)
-    output.write('\n')
-  output.write('  PatternProvider::Map map;\n')
-  output.write('  size_t len = sizeof(patterns) / sizeof(patterns[0]);\n')
-  output.write('  for (size_t i = 0; i < len; ++i) {\n')
-  output.write('    const JsonPattern& p = patterns[i];\n')
-  output.write('    MatchingPattern mp;\n')
-  output.write('    mp.language = LanguageCode(p.language);\n')
-  output.write('    mp.positive_pattern = p.positive_pattern;\n')
-  output.write('    mp.negative_pattern = '
+    output(line)
+    output('\n')
+  output('  PatternProvider::Map map;\n')
+  output('  size_t len = sizeof(patterns) / sizeof(patterns[0]);\n')
+  output('  for (size_t i = 0; i < len; ++i) {\n')
+  output('    const JsonPattern& p = patterns[i];\n')
+  output('    MatchingPattern mp;\n')
+  output('    mp.language = LanguageCode(p.language);\n')
+  output('    mp.positive_pattern = p.positive_pattern;\n')
+  output('    mp.negative_pattern = '
                'p.negative_pattern ? p.negative_pattern : "";\n')
-  output.write('    mp.positive_score = p.positive_score;\n')
-  output.write('    mp.match_field_input_types = p.match_field_input_types;\n')
-  output.write('    mp.match_field_attributes = p.match_field_attributes;\n')
-  output.write('    map[p.name][LanguageCode(p.language)].push_back(mp);\n')
-  output.write('  }\n')
-  output.write('  return map;\n')
-  output.write('}\n')
-  output.write('\n')
-  output.write('}')
+  output('    mp.positive_score = p.positive_score;\n')
+  output('    mp.match_field_input_types = p.match_field_input_types;\n')
+  output('    mp.match_field_attributes = p.match_field_attributes;\n')
+  output('    map[p.name][LanguageCode(p.language)].push_back(mp);\n')
+  output('  }\n')
+  output('  return map;\n')
+  output('}\n')
+  output('\n')
+  output('}')
 
 if __name__ == '__main__':
   input_file = sys.argv[1]
   output_file = sys.argv[2]
-  with open(input_file, 'r') as handle:
-    input = json.loads(handle.read())
-    with open(output_file, 'w') as output:
-      build_cpp_function(input, output)
+  with io.open(input_file, 'r', encoding='utf-8') as input_handle:
+    input_json = json.load(input_handle)
+    with io.open(output_file, 'w', encoding='utf-8') as output_handle:
+      build_cpp_function(input_json, output_handle)
diff --git a/components/autofill/core/common/autofill_constants.h b/components/autofill/core/common/autofill_constants.h
index 0742881..6e1efcc 100644
--- a/components/autofill/core/common/autofill_constants.h
+++ b/components/autofill/core/common/autofill_constants.h
@@ -68,12 +68,14 @@
 
 // Limits the number of times the value of a specific type can be filled into a
 // form.
-constexpr int kTypeValueFormFillingLimit = 9;
-
 // Credit card numbers are sometimes distributed between up to 19 individual
-// fields. Therefore, credit cards need a higher limit compared to
-// |kTypeValueFormFillingLimit|.
-constexpr int kCreditCardTypeValueFormFillingLimit = 19;
+// fields. Therefore, credit cards need a higher limit.
+// State fields are effecectively unlimited because there are sometimes hidden
+// fields select boxes, each with a list of states for one specific countries,
+// which are displayed only upon country selection.
+constexpr size_t kTypeValueFormFillingLimit = 9;
+constexpr size_t kCreditCardTypeValueFormFillingLimit = 19;
+constexpr size_t kStateTypeValueFormFillingLimit = 1000;
 
 }  // namespace autofill
 
diff --git a/components/blocked_content/popup_opener_tab_helper.cc b/components/blocked_content/popup_opener_tab_helper.cc
index 69e264d9..1471c40b 100644
--- a/components/blocked_content/popup_opener_tab_helper.cc
+++ b/components/blocked_content/popup_opener_tab_helper.cc
@@ -23,19 +23,6 @@
 
 namespace blocked_content {
 
-// static
-void PopupOpenerTabHelper::CreateForWebContents(
-    content::WebContents* contents,
-    const base::TickClock* tick_clock,
-    HostContentSettingsMap* settings_map) {
-  DCHECK(contents);
-  if (!FromWebContents(contents)) {
-    contents->SetUserData(UserDataKey(),
-                          base::WrapUnique(new PopupOpenerTabHelper(
-                              contents, tick_clock, settings_map)));
-  }
-}
-
 PopupOpenerTabHelper::~PopupOpenerTabHelper() {
   DCHECK(visibility_tracker_);
   base::TimeDelta total_visible_time =
diff --git a/components/blocked_content/popup_opener_tab_helper.h b/components/blocked_content/popup_opener_tab_helper.h
index 9d070f3..2bd8b06 100644
--- a/components/blocked_content/popup_opener_tab_helper.h
+++ b/components/blocked_content/popup_opener_tab_helper.h
@@ -36,12 +36,6 @@
     : public content::WebContentsObserver,
       public content::WebContentsUserData<PopupOpenerTabHelper> {
  public:
-  // |tick_clock| overrides the internal time for testing. This doesn't take
-  // ownership of |tick_clock| or |settings_map|, and they both must outlive the
-  // PopupOpenerTabHelper instance.
-  static void CreateForWebContents(content::WebContents* contents,
-                                   const base::TickClock* tick_clock,
-                                   HostContentSettingsMap* settings_map);
   ~PopupOpenerTabHelper() override;
 
   void OnOpenedPopup(PopupTracker* popup_tracker);
@@ -58,6 +52,9 @@
  private:
   friend class content::WebContentsUserData<PopupOpenerTabHelper>;
 
+  // |tick_clock| overrides the internal time for testing. This doesn't take
+  // ownership of |tick_clock| or |settings_map|, and they both must outlive the
+  // PopupOpenerTabHelper instance.
   PopupOpenerTabHelper(content::WebContents* web_contents,
                        const base::TickClock* tick_clock,
                        HostContentSettingsMap* settings_map);
diff --git a/components/captive_portal/content/captive_portal_tab_helper.cc b/components/captive_portal/content/captive_portal_tab_helper.cc
index 8a0a0fa..e65b751 100644
--- a/components/captive_portal/content/captive_portal_tab_helper.cc
+++ b/components/captive_portal/content/captive_portal_tab_helper.cc
@@ -18,20 +18,6 @@
 
 namespace captive_portal {
 
-// static
-void CaptivePortalTabHelper::CreateForWebContents(
-    content::WebContents* contents,
-    CaptivePortalService* captive_portal_service,
-    const CaptivePortalTabReloader::OpenLoginTabCallback&
-        open_login_tab_callback) {
-  if (FromWebContents(contents))
-    return;
-  contents->SetUserData(
-      UserDataKey(),
-      base::WrapUnique(new CaptivePortalTabHelper(
-          contents, captive_portal_service, open_login_tab_callback)));
-}
-
 CaptivePortalTabHelper::CaptivePortalTabHelper(
     content::WebContents* web_contents,
     CaptivePortalService* captive_portal_service,
diff --git a/components/captive_portal/content/captive_portal_tab_helper.h b/components/captive_portal/content/captive_portal_tab_helper.h
index ebe3ed4..c8c186f3 100644
--- a/components/captive_portal/content/captive_portal_tab_helper.h
+++ b/components/captive_portal/content/captive_portal_tab_helper.h
@@ -81,12 +81,6 @@
   bool is_captive_portal_window() const { return is_captive_portal_window_; }
   void set_is_captive_portal_window() { is_captive_portal_window_ = true; }
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      CaptivePortalService* captive_portal_service,
-      const CaptivePortalTabReloader::OpenLoginTabCallback&
-          open_login_tab_callback);
-
  private:
   friend class ::CaptivePortalBrowserTest;
   friend class CaptivePortalTabHelperTest;
diff --git a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
index 359ed34..1cf76a3 100644
--- a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
+++ b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -774,7 +774,7 @@
             in_shm_.Duplicate());
     ASSERT_EQ(dup_region.GetSize(), image_file->data_str.size());
     media::BitstreamBuffer bitstream_buffer(task_id, std::move(dup_region),
-                                            dup_region.GetSize());
+                                            image_file->data_str.size());
     decoder_->Decode(std::move(bitstream_buffer), hw_out_frame_);
   }
 }
diff --git a/components/content_settings/browser/page_specific_content_settings.cc b/components/content_settings/browser/page_specific_content_settings.cc
index 109abd2..b8f1950 100644
--- a/components/content_settings/browser/page_specific_content_settings.cc
+++ b/components/content_settings/browser/page_specific_content_settings.cc
@@ -109,22 +109,6 @@
   web_contents_ = nullptr;
 }
 
-// static
-void PageSpecificContentSettings::WebContentsHandler::CreateForWebContents(
-    content::WebContents* web_contents,
-    std::unique_ptr<Delegate> delegate) {
-  DCHECK(web_contents);
-  if (PageSpecificContentSettings::WebContentsHandler::FromWebContents(
-          web_contents)) {
-    return;
-  }
-
-  web_contents->SetUserData(
-      PageSpecificContentSettings::WebContentsHandler::UserDataKey(),
-      base::WrapUnique(new PageSpecificContentSettings::WebContentsHandler(
-          web_contents, std::move(delegate))));
-}
-
 PageSpecificContentSettings::WebContentsHandler::WebContentsHandler(
     content::WebContents* web_contents,
     std::unique_ptr<Delegate> delegate)
diff --git a/components/content_settings/browser/page_specific_content_settings.h b/components/content_settings/browser/page_specific_content_settings.h
index 6ae724a..00a5397 100644
--- a/components/content_settings/browser/page_specific_content_settings.h
+++ b/components/content_settings/browser/page_specific_content_settings.h
@@ -393,9 +393,6 @@
       : public content::WebContentsObserver,
         public content::WebContentsUserData<WebContentsHandler> {
    public:
-    static void CreateForWebContents(content::WebContents* web_contents,
-                                     std::unique_ptr<Delegate> delegate);
-
     explicit WebContentsHandler(content::WebContents* web_contents,
                                 std::unique_ptr<Delegate> delegate);
     ~WebContentsHandler() override;
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index 51d7f42..ce5adc735 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -22,7 +22,6 @@
 #include "net/cert/cert_verify_proc.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/ct_policy_status.h"
-#include "net/cert/do_nothing_ct_verifier.h"
 #include "net/cert/multi_threaded_cert_verifier.h"
 #include "net/dns/context_host_resolver.h"
 #include "net/dns/host_resolver.h"
@@ -773,8 +772,6 @@
     context_builder->SetCertVerifier(std::move(mock_cert_verifier));
   // Certificate Transparency is intentionally ignored in Cronet.
   // See //net/docs/certificate-transparency.md for more details.
-  context_builder->set_ct_verifier(
-      std::make_unique<net::DoNothingCTVerifier>());
   context_builder->set_ct_policy_enforcer(
       std::make_unique<net::DefaultCTPolicyEnforcer>());
   // TODO(mef): Use |config| to set cookies.
diff --git a/components/download/content/public/download_navigation_observer.cc b/components/download/content/public/download_navigation_observer.cc
index 32f49a0..88cc672 100644
--- a/components/download/content/public/download_navigation_observer.cc
+++ b/components/download/content/public/download_navigation_observer.cc
@@ -8,18 +8,6 @@
 
 namespace download {
 
-// static
-void DownloadNavigationObserver::CreateForWebContents(
-    content::WebContents* web_contents,
-    NavigationMonitor* navigation_monitor) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              std::make_unique<DownloadNavigationObserver>(
-                                  web_contents, navigation_monitor));
-  }
-}
-
 DownloadNavigationObserver::DownloadNavigationObserver(
     content::WebContents* web_contents,
     NavigationMonitor* navigation_monitor)
diff --git a/components/download/content/public/download_navigation_observer.h b/components/download/content/public/download_navigation_observer.h
index 6fa8fd0..93cf4b9e0 100644
--- a/components/download/content/public/download_navigation_observer.h
+++ b/components/download/content/public/download_navigation_observer.h
@@ -18,9 +18,6 @@
     : public content::WebContentsObserver,
       public content::WebContentsUserData<DownloadNavigationObserver> {
  public:
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   NavigationMonitor* navigation_monitor);
-
   DownloadNavigationObserver(content::WebContents* web_contents,
                              NavigationMonitor* navigation_monitor);
   ~DownloadNavigationObserver() override;
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc
index 0d1d9ded..9f46cc3 100644
--- a/components/drive/service/drive_api_service.cc
+++ b/components/drive/service/drive_api_service.cc
@@ -344,8 +344,8 @@
       kFileListFields, std::move(callback));
 }
 
-CancelCallback DriveAPIService::Search(const std::string& search_query,
-                                       FileListCallback callback) {
+CancelCallbackOnce DriveAPIService::Search(const std::string& search_query,
+                                           FileListCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!search_query.empty());
   DCHECK(!callback.is_null());
@@ -505,7 +505,7 @@
 CancelCallbackOnce DriveAPIService::DownloadFile(
     const base::FilePath& local_cache_path,
     const std::string& resource_id,
-    const DownloadActionCallback& download_action_callback,
+    DownloadActionCallback download_action_callback,
     const GetContentCallback& get_content_callback,
     ProgressCallback progress_callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -515,7 +515,8 @@
   return sender_->StartRequestWithAuthRetry(
       std::make_unique<DownloadFileRequest>(
           sender_.get(), url_generator_, resource_id, local_cache_path,
-          download_action_callback, get_content_callback, progress_callback));
+          std::move(download_action_callback), get_content_callback,
+          progress_callback));
 }
 
 CancelCallback DriveAPIService::DeleteResource(const std::string& resource_id,
diff --git a/components/drive/service/drive_api_service.h b/components/drive/service/drive_api_service.h
index c826a51..9cd57e3 100644
--- a/components/drive/service/drive_api_service.h
+++ b/components/drive/service/drive_api_service.h
@@ -137,7 +137,7 @@
   google_apis::CancelCallbackOnce GetFileListInDirectory(
       const std::string& directory_resource_id,
       google_apis::FileListCallback callback) override;
-  google_apis::CancelCallback Search(
+  google_apis::CancelCallbackOnce Search(
       const std::string& search_query,
       google_apis::FileListCallback callback) override;
   google_apis::CancelCallbackOnce SearchByTitle(
@@ -178,7 +178,7 @@
   google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback) override;
   google_apis::CancelCallback CopyResource(
diff --git a/components/drive/service/drive_service_interface.h b/components/drive/service/drive_service_interface.h
index 8f777e0..7e7feec9 100644
--- a/components/drive/service/drive_service_interface.h
+++ b/components/drive/service/drive_service_interface.h
@@ -241,7 +241,7 @@
   //
   // |search_query| must not be empty.
   // |callback| must not be null.
-  virtual google_apis::CancelCallback Search(
+  virtual google_apis::CancelCallbackOnce Search(
       const std::string& search_query,
       google_apis::FileListCallback callback) = 0;
 
@@ -429,7 +429,7 @@
   virtual google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback) = 0;
 
diff --git a/components/drive/service/dummy_drive_service.cc b/components/drive/service/dummy_drive_service.cc
index 6da99ce..18d7f4e 100644
--- a/components/drive/service/dummy_drive_service.cc
+++ b/components/drive/service/dummy_drive_service.cc
@@ -70,8 +70,8 @@
   return CancelCallbackOnce();
 }
 
-CancelCallback DummyDriveService::Search(const std::string& search_query,
-                                         FileListCallback callback) {
+CancelCallbackOnce DummyDriveService::Search(const std::string& search_query,
+                                             FileListCallback callback) {
   return CancelCallback();
 }
 
@@ -143,7 +143,7 @@
 CancelCallbackOnce DummyDriveService::DownloadFile(
     const base::FilePath& local_cache_path,
     const std::string& resource_id,
-    const DownloadActionCallback& download_action_callback,
+    DownloadActionCallback download_action_callback,
     const GetContentCallback& get_content_callback,
     ProgressCallback progress_callback) {
   return CancelCallback();
diff --git a/components/drive/service/dummy_drive_service.h b/components/drive/service/dummy_drive_service.h
index 425b7e9..42d80a7 100644
--- a/components/drive/service/dummy_drive_service.h
+++ b/components/drive/service/dummy_drive_service.h
@@ -41,7 +41,7 @@
   google_apis::CancelCallbackOnce GetFileListInDirectory(
       const std::string& directory_resource_id,
       google_apis::FileListCallback callback) override;
-  google_apis::CancelCallback Search(
+  google_apis::CancelCallbackOnce Search(
       const std::string& search_query,
       google_apis::FileListCallback callback) override;
   google_apis::CancelCallbackOnce SearchByTitle(
@@ -82,7 +82,7 @@
   google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback) override;
   google_apis::CancelCallback CopyResource(
diff --git a/components/drive/service/fake_drive_service.cc b/components/drive/service/fake_drive_service.cc
index 340e91a..0293f527 100644
--- a/components/drive/service/fake_drive_service.cc
+++ b/components/drive/service/fake_drive_service.cc
@@ -440,8 +440,8 @@
   return CancelCallbackOnce();
 }
 
-CancelCallback FakeDriveService::Search(const std::string& search_query,
-                                        FileListCallback callback) {
+CancelCallbackOnce FakeDriveService::Search(const std::string& search_query,
+                                            FileListCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!search_query.empty());
 
@@ -759,7 +759,7 @@
 CancelCallbackOnce FakeDriveService::DownloadFile(
     const base::FilePath& local_cache_path,
     const std::string& resource_id,
-    const DownloadActionCallback& download_action_callback,
+    DownloadActionCallback download_action_callback,
     const GetContentCallback& get_content_callback,
     ProgressCallback progress_callback) {
   base::ThreadRestrictions::ScopedAllowIO allow_io;
@@ -768,16 +768,16 @@
 
   if (offline_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(download_action_callback, DRIVE_NO_CONNECTION,
-                                  base::FilePath()));
+        FROM_HERE, base::BindOnce(std::move(download_action_callback),
+                                  DRIVE_NO_CONNECTION, base::FilePath()));
     return CancelCallbackOnce();
   }
 
   EntryInfo* entry = FindEntryByResourceId(resource_id);
   if (!entry || entry->change_resource.file()->IsHostedDocument()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(download_action_callback, HTTP_NOT_FOUND,
-                                  base::FilePath()));
+        FROM_HERE, base::BindOnce(std::move(download_action_callback),
+                                  HTTP_NOT_FOUND, base::FilePath()));
     return CancelCallbackOnce();
   }
 
@@ -801,8 +801,8 @@
   if (!test_util::WriteStringToFile(local_cache_path, content_data)) {
     // Failed to write the content.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(download_action_callback, DRIVE_FILE_ERROR,
-                                  base::FilePath()));
+        FROM_HERE, base::BindOnce(std::move(download_action_callback),
+                                  DRIVE_FILE_ERROR, base::FilePath()));
     return CancelCallbackOnce();
   }
 
@@ -816,8 +816,8 @@
         FROM_HERE, base::BindOnce(progress_callback, file_size, file_size));
   }
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(download_action_callback, HTTP_SUCCESS, local_cache_path));
+      FROM_HERE, base::BindOnce(std::move(download_action_callback),
+                                HTTP_SUCCESS, local_cache_path));
   return google_apis::CancelCallbackOnce();
 }
 
diff --git a/components/drive/service/fake_drive_service.h b/components/drive/service/fake_drive_service.h
index 9a99f90f..f77076a 100644
--- a/components/drive/service/fake_drive_service.h
+++ b/components/drive/service/fake_drive_service.h
@@ -143,7 +143,7 @@
       google_apis::FileListCallback callback) override;
   // See the comment for EntryMatchWidthQuery() in .cc file for details about
   // the supported search query types.
-  google_apis::CancelCallback Search(
+  google_apis::CancelCallbackOnce Search(
       const std::string& search_query,
       google_apis::FileListCallback callback) override;
   google_apis::CancelCallbackOnce SearchByTitle(
@@ -184,7 +184,7 @@
   google_apis::CancelCallbackOnce DownloadFile(
       const base::FilePath& local_cache_path,
       const std::string& resource_id,
-      const google_apis::DownloadActionCallback& download_action_callback,
+      google_apis::DownloadActionCallback download_action_callback,
       const google_apis::GetContentCallback& get_content_callback,
       google_apis::ProgressCallback progress_callback) override;
   google_apis::CancelCallback CopyResource(
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index ae38abc..b243e70 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/ui.gni")
 import("//chrome/common/features.gni")
@@ -76,6 +77,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//cc",
     "//components/viz/host",
     "//device/gamepad",
@@ -119,7 +121,7 @@
     "//ui/base/dragdrop/mojom:mojom_headers",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [
       "//ash",
       "//ash/keyboard/ui",
@@ -221,7 +223,7 @@
     "//ui/wm",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "test/exo_test_base.cc",
       "test/exo_test_base.h",
@@ -275,7 +277,7 @@
     deps += [ "//ui/ozone" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "../../ui/events/ozone/gamepad/gamepad_event.cc",
       "buffer_unittest.cc",
@@ -311,6 +313,7 @@
       "//ash:test_support",
       "//ash/keyboard/ui",
       "//ash/public/cpp",
+      "//build:chromeos_buildflags",
       "//chromeos/constants",
       "//chromeos/ui/base",
       "//chromeos/ui/frame",
@@ -336,6 +339,7 @@
     ":unit_tests",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//cc:test_support",
     "//components/viz/test:test_support",
     "//device/gamepad:test_helpers",
@@ -355,7 +359,7 @@
     deps += [ "//components/exo/wayland:unit_tests" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "../../ash/test/ash_test_suite.cc",
       "../../ash/test/ash_test_suite.h",
diff --git a/components/exo/display.cc b/components/exo/display.cc
index c64bb1f..4ea48f8 100644
--- a/components/exo/display.cc
+++ b/components/exo/display.cc
@@ -12,6 +12,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/data_device.h"
 #include "components/exo/file_helper.h"
 #include "components/exo/input_method_surface_manager.h"
@@ -34,7 +35,7 @@
 #include "ui/ozone/public/ozone_switches.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/wm/desks/desks_util.h"
 #include "components/exo/client_controlled_shell_surface.h"
@@ -58,7 +59,7 @@
 {
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 Display::Display(
     std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
     std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
@@ -70,7 +71,7 @@
       file_helper_(std::move(file_helper)),
       client_native_pixmap_factory_(
           gfx::CreateClientNativePixmapFactoryDmabuf()) {}
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 Display::~Display() {
   Shutdown();
@@ -136,7 +137,7 @@
 }
 #endif  // defined(USE_OZONE)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<ShellSurface> Display::CreateShellSurface(Surface* surface) {
   TRACE_EVENT1("exo", "Display::CreateShellSurface", "surface",
                surface->AsTracedValue());
@@ -259,7 +260,7 @@
   }
   return toast_surface;
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface,
                                                       Surface* parent) {
diff --git a/components/exo/display.h b/components/exo/display.h
index 8690b03..e64427ad 100644
--- a/components/exo/display.h
+++ b/components/exo/display.h
@@ -12,6 +12,7 @@
 
 #include "base/macros.h"
 #include "base/memory/unsafe_shared_memory_region.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/seat.h"
 
 #if defined(USE_OZONE)
@@ -37,7 +38,7 @@
 class SubSurface;
 class Surface;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class InputMethodSurface;
 class ShellSurface;
 class ToastSurface;
@@ -56,13 +57,13 @@
  public:
   Display();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   Display(
       std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
       std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
       std::unique_ptr<ToastSurfaceManager> toast_surface_manager,
       std::unique_ptr<FileHelper> file_helper);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   ~Display();
 
@@ -85,7 +86,7 @@
       bool y_invert);
 #endif  // defined(USE_OZONE)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Creates a shell surface for an existing surface.
   std::unique_ptr<ShellSurface> CreateShellSurface(Surface* surface);
 
@@ -115,7 +116,7 @@
       Surface* surface,
       double default_device_scale_factor,
       bool default_scale_cancellation);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Creates a sub-surface for an existing surface. The sub-surface will be
   // a child of |parent|.
@@ -128,18 +129,18 @@
   // Obtains seat instance.
   Seat* seat() { return &seat_; }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   InputMethodSurfaceManager* input_method_surface_manager() {
     return input_method_surface_manager_.get();
   }
 #endif
 
  private:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<NotificationSurfaceManager> notification_surface_manager_;
   std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager_;
   std::unique_ptr<ToastSurfaceManager> toast_surface_manager_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   std::unique_ptr<FileHelper> file_helper_;
   Seat seat_;
diff --git a/components/exo/drag_drop_operation.cc b/components/exo/drag_drop_operation.cc
index 97d0080..78cf22f9 100644
--- a/components/exo/drag_drop_operation.cc
+++ b/components/exo/drag_drop_operation.cc
@@ -8,6 +8,7 @@
 #include "base/check.h"
 #include "base/strings/string_split.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/data_offer.h"
 #include "components/exo/data_source.h"
 #include "components/exo/file_helper.h"
@@ -29,10 +30,10 @@
 #include "ui/gfx/transform_util.h"
 #include "url/gurl.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/drag_drop/drag_drop_controller.h"
 #include "components/exo/extended_drag_source.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace exo {
 
@@ -58,7 +59,7 @@
   return dnd_operations;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 DndAction DragOperationsToPreferredDndAction(int op) {
   if (op & ui::DragDropTypes::DragOperation::DRAG_COPY)
     return DndAction::kCopy;
@@ -168,7 +169,7 @@
       event_source_(event_source) {
   aura::Window* root_window = origin_->get()->window()->GetRootWindow();
   DCHECK(root_window);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   drag_drop_controller_ = static_cast<ash::DragDropController*>(
       aura::client::GetDragDropClient(root_window));
 #else
@@ -181,7 +182,7 @@
 
   drag_drop_controller_->AddObserver(this);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   extended_drag_source_ = ExtendedDragSource::Get();
   if (extended_drag_source_) {
     drag_drop_controller_->set_toplevel_window_drag_delegate(
@@ -224,7 +225,7 @@
   if (drag_drop_controller_->IsDragDropInProgress() && started_by_this_object_)
     drag_drop_controller_->DragCancel();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (extended_drag_source_)
     ResetExtendedDragSource();
 #endif
@@ -274,7 +275,7 @@
   if (os_exchange_data_) {
     os_exchange_data_->provider().SetDragImage(icon_skia, icon_offset);
   } else {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     drag_drop_controller_->SetDragImage(icon_skia, icon_offset);
 #endif
   }
@@ -344,7 +345,7 @@
 
 void DragDropOperation::OnDragEnded() {}
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void DragDropOperation::OnDragActionsChanged(int actions) {
   if (!started_by_this_object_)
     return;
diff --git a/components/exo/drag_drop_operation.h b/components/exo/drag_drop_operation.h
index 616b2a95..c7b2782 100644
--- a/components/exo/drag_drop_operation.h
+++ b/components/exo/drag_drop_operation.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "build/chromeos_buildflags.h"
 #include "components/exo/data_device.h"
 #include "components/exo/data_offer_observer.h"
 #include "components/exo/data_source_observer.h"
@@ -17,7 +18,7 @@
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
 #include "ui/gfx/geometry/point_f.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/exo/extended_drag_source.h"
 #endif
 
@@ -50,7 +51,7 @@
 // or if another drag operation races with this one to start and wins.
 class DragDropOperation : public DataSourceObserver,
                           public SurfaceObserver,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
                           public ExtendedDragSource::Observer,
 #endif
                           public aura::client::DragDropClientObserver {
@@ -76,7 +77,7 @@
   // aura::client::DragDropClientObserver:
   void OnDragStarted() override;
   void OnDragEnded() override;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnDragActionsChanged(int actions) override;
 
   // ExtendedDragSource::Observer:
@@ -111,7 +112,7 @@
   // directly. Use ScheduleStartDragDropOperation instead.
   void StartDragDropOperation();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void ResetExtendedDragSource();
 #endif
 
@@ -120,11 +121,11 @@
   std::unique_ptr<ScopedSurface> origin_;
   gfx::PointF drag_start_point_;
   std::unique_ptr<ui::OSExchangeData> os_exchange_data_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::DragDropController* drag_drop_controller_;
 #else
   aura::client::DragDropClient* drag_drop_controller_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   base::RepeatingClosure counter_;
 
@@ -142,7 +143,7 @@
 
   ui::mojom::DragEventSource event_source_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ExtendedDragSource* extended_drag_source_;
 #endif
 
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 1d88b9f4..27dad17 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -10,6 +10,7 @@
 #include "base/feature_list.h"
 #include "base/optional.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/input_trace.h"
 #include "components/exo/pointer_constraint_delegate.h"
 #include "components/exo/pointer_delegate.h"
@@ -41,7 +42,7 @@
 #include "ui/gfx/transform_util.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/wm/window_util.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -95,7 +96,7 @@
 }
 
 int GetContainerIdForMouseCursor() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return ash::kShellWindowId_MouseCursorContainer;
 #else
   NOTIMPLEMENTED();
@@ -239,7 +240,7 @@
   // Pointer lock is a chromeos-only feature (i.e. the chromeos::features
   // namespace only exists in chromeos builds). So we do not compile pointer
   // lock support unless we are on chromeos.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   Surface* constrained_surface = delegate->GetConstrainedSurface();
   // Pointer lock should be enabled for ARC by default. The kExoPointerLock
   // should only apply to Crostini windows.
@@ -419,7 +420,7 @@
     // TODO(b/161755250): the ifdef is only necessary because of the feature
     // flag. This code should work fine on non-cros.
     base::Optional<gfx::Vector2dF> ordinal_motion = base::nullopt;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (event->flags() & ui::EF_UNADJUSTED_MOUSE &&
         base::FeatureList::IsEnabled(chromeos::features::kExoOrdinalMotion)) {
       ordinal_motion = event->movement();
diff --git a/components/exo/pointer_unittest.cc b/components/exo/pointer_unittest.cc
index da10ec0..d9322e0 100644
--- a/components/exo/pointer_unittest.cc
+++ b/components/exo/pointer_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/buffer.h"
 #include "components/exo/data_source.h"
 #include "components/exo/data_source_delegate.h"
@@ -41,7 +42,7 @@
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/constants/chromeos_features.h"
 #endif
 
@@ -1115,7 +1116,7 @@
   //
   // TODO(b/161755250): the ifdef is only necessary because of the feature
   // flag. This code should work fine on non-cros.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   new_location = new_location + gfx::Vector2d(1, 1);
   ui::MouseEvent ev2(ui::ET_MOUSE_MOVED, new_location, new_location,
                      ui::EventTimeForNow(), generator.flags(), 0);
@@ -1133,7 +1134,7 @@
   pointer->UnregisterRelativePointerDelegate(&relative_delegate);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PointerTest, ConstrainPointer) {
   auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list->InitAndEnableFeature(
@@ -1200,7 +1201,7 @@
 }
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PointerTest, ConstrainPointerFailsWhenSurfaceIsNotFocused) {
   auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list->InitAndEnableFeature(
@@ -1262,7 +1263,7 @@
 }
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PointerTest, UnconstrainPointerWhenSurfaceIsDestroyed) {
   auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list->InitAndEnableFeature(
@@ -1306,7 +1307,7 @@
 }
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PointerTest, UnconstrainPointerWhenWindowLosesFocus) {
   auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list->InitAndEnableFeature(
diff --git a/components/exo/seat.cc b/components/exo/seat.cc
index 2a0cd99..658eb80b 100644
--- a/components/exo/seat.cc
+++ b/components/exo/seat.cc
@@ -7,9 +7,9 @@
 #include <memory>
 #include "ui/gfx/geometry/point_f.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/shell.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #include "base/auto_reset.h"
 #include "base/barrier_closure.h"
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/data_source.h"
 #include "components/exo/drag_drop_operation.h"
 #include "components/exo/mime_utils.h"
@@ -61,7 +62,7 @@
   // null. https://crbug.com/856230
   if (ui::PlatformEventSource::GetInstance())
     ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ui_lock_controller_ = std::make_unique<UILockController>(this);
 
   // Seat needs to be registered as observers before any Keyboard,
@@ -83,7 +84,7 @@
     return;
   shutdown_ = true;
   DCHECK(!selection_source_) << "DataSource must be released before Seat";
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::Shell::Get()->ime_controller()->RemoveObserver(this);
 #endif
   WMHelper::GetInstance()->RemoveFocusObserver(this);
@@ -200,7 +201,7 @@
                        base::OnceClosure callback,
                        const std::string& mime_type,
                        const std::vector<uint8_t>& data) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   data_decoder::DecodeImageIsolated(
       data, data_decoder::mojom::ImageCodec::DEFAULT, false,
       std::numeric_limits<int64_t>::max(), gfx::Size(),
@@ -208,10 +209,10 @@
                      std::move(callback), writer));
 #else
   std::move(callback).Run();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void Seat::OnImageDecoded(base::OnceClosure callback,
                           scoped_refptr<RefCountedScopedClipboardWriter> writer,
                           const SkBitmap& bitmap) {
@@ -219,7 +220,7 @@
     writer->WriteImage(bitmap);
   std::move(callback).Run();
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void Seat::OnFilenamesRead(
     scoped_refptr<RefCountedScopedClipboardWriter> writer,
@@ -314,7 +315,7 @@
         break;
     }
   }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   xkb_tracker_->UpdateKeyboardModifiers(event->flags());
 #endif
 }
@@ -329,7 +330,7 @@
   selection_source_.reset();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 ////////////////////////////////////////////////////////////////////////////////
 // ash::ImeControllerImpl::Observer overrides:
 
diff --git a/components/exo/seat.h b/components/exo/seat.h
index ff6860a..e7b3f54c 100644
--- a/components/exo/seat.h
+++ b/components/exo/seat.h
@@ -9,6 +9,7 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/data_source_observer.h"
 #include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/client/focus_change_observer.h"
@@ -19,7 +20,7 @@
 #include "ui/events/keycodes/dom/dom_codes.h"
 #include "ui/events/platform/platform_event_observer.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/ime/ime_controller_impl.h"
 #include "components/exo/ui_lock_controller.h"
 #endif
@@ -47,7 +48,7 @@
              public ui::PlatformEventObserver,
              public ui::EventHandler,
              public ui::ClipboardObserver,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
              public ash::ImeControllerImpl::Observer,
 #endif
              public DataSourceObserver {
@@ -69,7 +70,7 @@
     return pressed_keys_;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const XkbTracker* xkb_tracker() const { return xkb_tracker_.get(); }
 #endif
 
@@ -111,7 +112,7 @@
   // Overridden from DataSourceObserver:
   void OnDataSourceDestroying(DataSource* source) override;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Overridden from ash::ImeControllerImpl::Observer:
   void OnCapsLockChanged(bool enabled) override;
   void OnKeyboardLayoutNameChanged(const std::string& layout_name) override;
@@ -149,11 +150,11 @@
                    base::OnceClosure callback,
                    const std::string& mime_type,
                    const std::vector<uint8_t>& data);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnImageDecoded(base::OnceClosure callback,
                       scoped_refptr<RefCountedScopedClipboardWriter> writer,
                       const SkBitmap& bitmap);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   void OnFilenamesRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
                        base::OnceClosure callback,
                        const std::string& mime_type,
@@ -181,10 +182,10 @@
 
   bool shutdown_ = false;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<UILockController> ui_lock_controller_;
   std::unique_ptr<XkbTracker> xkb_tracker_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   base::WeakPtrFactory<Seat> weak_ptr_factory_{this};
 
diff --git a/components/exo/server/BUILD.gn b/components/exo/server/BUILD.gn
index 0dc6cae..69b5c95 100644
--- a/components/exo/server/BUILD.gn
+++ b/components/exo/server/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-assert(is_chromeos)
+import("//build/config/chromeos/ui_mode.gni")
+
+assert(is_chromeos_ash)
 
 source_set("server") {
   sources = [
diff --git a/components/exo/shell_surface_util.cc b/components/exo/shell_surface_util.cc
index 7006d56..7b094a3e 100644
--- a/components/exo/shell_surface_util.cc
+++ b/components/exo/shell_surface_util.cc
@@ -8,6 +8,7 @@
 
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/permission.h"
 #include "components/exo/shell_surface_base.h"
 #include "components/exo/surface.h"
@@ -20,9 +21,9 @@
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/window_util.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/ui/base/window_properties.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Permission*)
 
@@ -105,13 +106,13 @@
 }
 
 void SetShellUseImmersiveForFullscreen(aura::Window* window, bool value) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   window->SetProperty(chromeos::kImmersiveImpliedByFullscreen, value);
 
   // Ensure the shelf is fully hidden in plain fullscreen, but shown
   // (auto-hides based on mouse movement) when in immersive fullscreen.
   window->SetProperty(chromeos::kHideShelfWhenFullscreenKey, !value);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void SetShellClientAccessibilityId(aura::Window* window,
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 7dd665c..b52ebf2 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -16,6 +16,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/buffer.h"
 #include "components/exo/frame_sink_resource_manager.h"
 #include "components/exo/shell_surface_util.h"
@@ -53,10 +54,10 @@
 #include "ui/gfx/transform_util.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/display/output_protection_delegate.h"
 #include "ash/wm/desks/desks_util.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Surface*)
 
@@ -117,11 +118,11 @@
 }
 
 bool IsDeskContainer(aura::Window* container) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return ash::desks_util::IsDeskContainer(container);
 #else
   return container->id() == ash::kShellWindowId_DefaultContainerDeprecated;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 class CustomWindowDelegate : public aura::WindowDelegate {
@@ -691,11 +692,11 @@
         cached_state_.basic_state.buffer_transform !=
             state_.basic_state.buffer_transform;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     bool needs_output_protection =
         cached_state_.basic_state.only_visible_on_secure_output !=
         state_.basic_state.only_visible_on_secure_output;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     bool cached_invert_y = false;
 
@@ -721,7 +722,7 @@
       window_->TrackOcclusionState();
     }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (needs_output_protection) {
       if (!output_protection_) {
         output_protection_ =
@@ -735,7 +736,7 @@
 
       output_protection_->SetProtection(protection_mask, base::DoNothing());
     }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     // We update contents if Attach() has been called since last commit.
     if (has_cached_contents_) {
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 21b36df..5bd6e015 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "build/chromeos_buildflags.h"
 #include "cc/base/region.h"
 #include "components/exo/layer_tree_frame_sink_holder.h"
 #include "components/exo/surface_delegate.h"
@@ -455,9 +456,9 @@
   // Surface observer list. Surface does not own the observers.
   base::ObserverList<SurfaceObserver, true>::Unchecked observers_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<ash::OutputProtectionDelegate> output_protection_;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   viz::SurfaceId first_embedded_surface_id_;
   viz::SurfaceId latest_embedded_surface_id_;
diff --git a/components/exo/test/run_all_unittests.cc b/components/exo/test/run_all_unittests.cc
index 0f1c677..a844f5a 100644
--- a/components/exo/test/run_all_unittests.cc
+++ b/components/exo/test/run_all_unittests.cc
@@ -4,8 +4,9 @@
 
 #include "base/bind.h"
 #include "base/test/launcher/unit_test_launcher.h"
+#include "build/chromeos_buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/test/ash_test_suite.h"
 #else
 #include "components/exo/test/exo_test_suite_aura.h"
@@ -16,7 +17,7 @@
 #endif
 
 int main(int argc, char** argv) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::AshTestSuite test_suite(argc, argv);
 #else
   exo::test::ExoTestSuiteAura test_suite(argc, argv);
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 5b8d0d9..fbb0efa0 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ozone.gni")
 import("//build/config/ui.gni")
 import("//gpu/vulkan/features.gni")
@@ -63,6 +64,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//components/exo",
     "//components/exo/wayland/protocol:aura_shell_protocol",
     "//device/gamepad",
@@ -118,7 +120,7 @@
       "//ui/ozone",
     ]
 
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       deps += [
         "//ash",
         "//ash/public/cpp",
@@ -140,7 +142,7 @@
     deps += [ "//third_party/wayland-protocols:fullscreen_shell_protocol" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "wayland_keyboard_delegate.cc",
       "wayland_keyboard_delegate.h",
@@ -195,6 +197,7 @@
   deps = [
     ":wayland",
     "//base",
+    "//build:chromeos_buildflags",
     "//components/exo",
     "//components/exo:test_support",
     "//components/exo/wayland/fuzzer:unit_tests",
@@ -205,7 +208,7 @@
     "//third_party/wayland:wayland_client",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "wayland_keyboard_delegate_unittest.cc",
       "wayland_positioner_unittest.cc",
@@ -447,7 +450,7 @@
 
   data_deps = []
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     data_deps += [
       "//ash/resources:ash_test_resources_100_percent",
       "//ash/resources:ash_test_resources_200_percent",
@@ -493,7 +496,7 @@
 
   data_deps = []
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "../../../ash/test/ash_test_suite.cc",
       "../../../ash/test/ash_test_suite.h",
@@ -539,7 +542,7 @@
     "//ui/gl:test_support",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//ash:test_support" ]
   }
 
diff --git a/components/exo/wayland/fuzzer/BUILD.gn b/components/exo/wayland/fuzzer/BUILD.gn
index bc613a4..57435968 100644
--- a/components/exo/wayland/fuzzer/BUILD.gn
+++ b/components/exo/wayland/fuzzer/BUILD.gn
@@ -102,6 +102,7 @@
     ":actions",
     ":harness",
     "//base",
+    "//build:chromeos_buildflags",
     "//components/exo",
     "//components/exo:test_support",
     "//components/exo/wayland",
diff --git a/components/exo/wayland/fuzzer/harness_unittest.cc b/components/exo/wayland/fuzzer/harness_unittest.cc
index d2c8d7fd..8234628 100644
--- a/components/exo/wayland/fuzzer/harness_unittest.cc
+++ b/components/exo/wayland/fuzzer/harness_unittest.cc
@@ -7,12 +7,13 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/display.h"
 #include "components/exo/test/exo_test_base_views.h"
 #include "components/exo/wayland/fuzzer/actions.pb.h"
 #include "components/exo/wayland/server.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/exo/test/exo_test_base.h"
 #endif
 
@@ -23,7 +24,7 @@
 // Use ExoTestBase on Chrome OS because Server starts to depends on ash::Shell,
 // which is unavailable on other platforms so then ExoTestBaseViews instead.
 using TestBase =
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     test::ExoTestBase
 #else
     test::ExoTestBaseViews
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 20b98bc..4ccf798 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -41,6 +41,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/posix/eintr_wrapper.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/display.h"
 #include "components/exo/wayland/serial_tracker.h"
 #include "components/exo/wayland/wayland_display_output.h"
@@ -61,7 +62,7 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/system/sys_info.h"
 #include "components/exo/wayland/wl_shell.h"
 #include "components/exo/wayland/xdg_shell.h"
@@ -179,7 +180,7 @@
   }
   wl_global_create(wl_display_.get(), &zaura_shell_interface,
                    kZAuraShellVersion, display_, bind_aura_shell);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
                    bind_shell);
   wl_global_create(wl_display_.get(), &zcr_cursor_shapes_v1_interface, 1,
@@ -256,7 +257,7 @@
   }
 
   const base::FilePath runtime_dir(runtime_dir_str);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On debugging chromeos-chrome on linux platform,
   // try to ensure the directory if missing.
   if (!base::SysInfo::IsRunningOnChromeOS()) {
@@ -264,7 +265,7 @@
           base::CreateDirectory(runtime_dir))
         << "Failed to create XDG_RUNTIME_DIR";
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   std::string socket_name(kSocketName);
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/components/exo/wayland/server.h b/components/exo/wayland/server.h
index 00084f4..82a6e55 100644
--- a/components/exo/wayland/server.h
+++ b/components/exo/wayland/server.h
@@ -14,6 +14,8 @@
 #include "components/exo/wayland/scoped_wl.h"
 #include "ui/display/display_observer.h"
 
+#include "build/chromeos_buildflags.h"
+
 struct wl_resource;
 struct wl_client;
 
@@ -74,7 +76,7 @@
   std::unique_ptr<WaylandDataDeviceManager> data_device_manager_data_;
   std::unique_ptr<WaylandSeat> seat_data_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<WaylandTextInputManager> zwp_text_manager_data_;
   std::unique_ptr<WaylandZxdgShell> zxdg_shell_data_;
   std::unique_ptr<WaylandXdgShell> xdg_shell_data_;
diff --git a/components/exo/wayland/server_unittest.cc b/components/exo/wayland/server_unittest.cc
index ef827b1..bbff81b 100644
--- a/components/exo/wayland/server_unittest.cc
+++ b/components/exo/wayland/server_unittest.cc
@@ -16,11 +16,12 @@
 #include "base/process/process_handle.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/display.h"
 #include "components/exo/test/exo_test_base_views.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/exo/test/exo_test_base.h"
 #endif
 
@@ -38,7 +39,7 @@
 // Use ExoTestBase on Chrome OS because Server starts to depends on ash::Shell,
 // which is unavailable on other platforms so then ExoTestBaseViews instead.
 using TestBase =
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     test::ExoTestBase
 #else
     test::ExoTestBaseViews
diff --git a/components/exo/wayland/wl_compositor.cc b/components/exo/wayland/wl_compositor.cc
index 8ee31c09b..ad2b5f7a 100644
--- a/components/exo/wayland/wl_compositor.cc
+++ b/components/exo/wayland/wl_compositor.cc
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/buffer.h"
 #include "components/exo/display.h"
 #include "components/exo/surface.h"
@@ -17,7 +18,7 @@
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/display/types/display_constants.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/exo/wayland/zwp_linux_explicit_synchronization.h"
 #endif
 
@@ -132,7 +133,7 @@
 void surface_commit(wl_client* client, wl_resource* resource) {
   Surface* surface = GetUserDataAs<Surface>(resource);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   if (!linux_surface_synchronization_validate_commit(surface))
     return;
 #endif
diff --git a/components/exo/wayland/wl_seat.cc b/components/exo/wayland/wl_seat.cc
index 1b50eaa..bfa5d39 100644
--- a/components/exo/wayland/wl_seat.cc
+++ b/components/exo/wayland/wl_seat.cc
@@ -7,6 +7,7 @@
 #include <wayland-server-core.h>
 #include <wayland-server-protocol-core.h>
 
+#include "build/chromeos_buildflags.h"
 #include "components/exo/pointer.h"
 #include "components/exo/touch.h"
 #include "components/exo/wayland/serial_tracker.h"
@@ -15,10 +16,10 @@
 #include "components/exo/wayland/wayland_touch_delegate.h"
 #include "ui/base/buildflags.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/exo/keyboard.h"
 #include "components/exo/wayland/wayland_keyboard_delegate.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace exo {
 namespace wayland {
@@ -46,7 +47,7 @@
 const struct wl_pointer_interface pointer_implementation = {pointer_set_cursor,
                                                             pointer_release};
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 ////////////////////////////////////////////////////////////////////////////////
 // wl_keyboard_interface:
 
@@ -59,7 +60,7 @@
 const struct wl_keyboard_interface keyboard_implementation = {keyboard_release};
 
 #endif  // BUILDFLAG(USE_XKBCOMMON)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 ////////////////////////////////////////////////////////////////////////////////
 // wl_touch_interface:
 
@@ -86,7 +87,7 @@
 }
 
 void seat_get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) {
-#if defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(USE_XKBCOMMON)
   auto* data = GetUserDataAs<WaylandSeat>(resource);
 
   uint32_t version = wl_resource_get_version(resource);
@@ -101,7 +102,7 @@
                     std::move(keyboard));
 #else
   NOTIMPLEMENTED();
-#endif  // defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(USE_XKBCOMMON)
 }
 
 void seat_get_touch(wl_client* client, wl_resource* resource, uint32_t id) {
@@ -136,9 +137,9 @@
     wl_seat_send_name(resource, "default");
   uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH;
 
-#if defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
+#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(USE_XKBCOMMON)
   capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
-#endif  // defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(USE_XKBCOMMON)
   wl_seat_send_capabilities(resource, capabilities);
 }
 
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc
index 2a1a369..f1b1650 100644
--- a/components/exo/wayland/zaura_shell.cc
+++ b/components/exo/wayland/zaura_shell.cc
@@ -17,6 +17,7 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/wm/window_state.h"
 #include "base/strings/string_number_conversions.h"
+#include "build/chromeos_buildflags.h"
 #include "components/exo/wayland/server_util.h"
 #include "components/exo/wayland/wayland_display_observer.h"
 #include "components/exo/wayland/wl_output.h"
@@ -31,12 +32,12 @@
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/public/activation_client.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "components/exo/wm_helper_chromeos.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace exo {
 namespace wayland {
@@ -329,7 +330,7 @@
 void AuraSurface::ComputeAndSendOcclusionFraction(
     const aura::Window::OcclusionState occlusion_state,
     const SkRegion& occluded_region) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Should re-write in locked case - we don't want to trigger PIP upon
   // locking the screen.
   // TODO(afakhry): We may also want to have special behaviour here for virtual
@@ -338,7 +339,7 @@
     SendOcclusionFraction(0.0f);
     return;
   }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   auto* window = surface_->window();
   float fraction_occluded = 0.0f;
@@ -469,7 +470,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // aura_shell_interface:
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Implements aura shell interface and monitors workspace state needed
 // for the aura shell interface.
 class WaylandAuraShell : public ash::TabletModeObserver {
@@ -512,7 +513,7 @@
   // The aura shell resource associated with observer.
   wl_resource* const aura_shell_resource_;
 };
-#endif  // OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH))
 
 void aura_shell_get_aura_surface(wl_client* client,
                                  wl_resource* resource,
@@ -563,7 +564,7 @@
       wl_resource_create(client, &zaura_shell_interface,
                          std::min(version, kZAuraShellVersion), id);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   SetImplementation(resource, &aura_shell_implementation,
                     std::make_unique<WaylandAuraShell>(resource));
 #else
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc
index e1ae023..91a11b324 100644
--- a/components/favicon/content/content_favicon_driver.cc
+++ b/components/favicon/content/content_favicon_driver.cc
@@ -20,18 +20,6 @@
 
 namespace favicon {
 
-// static
-void ContentFaviconDriver::CreateForWebContents(
-    content::WebContents* web_contents,
-    CoreFaviconService* favicon_service) {
-  if (FromWebContents(web_contents))
-    return;
-
-  web_contents->SetUserData(UserDataKey(),
-                            base::WrapUnique(new ContentFaviconDriver(
-                                web_contents, favicon_service)));
-}
-
 gfx::Image ContentFaviconDriver::GetFavicon() const {
   // Like GetTitle(), we also want to use the favicon for the last committed
   // entry rather than a pending navigation entry.
diff --git a/components/favicon/content/content_favicon_driver.h b/components/favicon/content/content_favicon_driver.h
index 8226afb..29c6f97 100644
--- a/components/favicon/content/content_favicon_driver.h
+++ b/components/favicon/content/content_favicon_driver.h
@@ -30,9 +30,6 @@
  public:
   ~ContentFaviconDriver() override;
 
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   CoreFaviconService* favicon_service);
-
   // Returns the current tab's favicon URLs. If this is empty,
   // DidUpdateFaviconURL has not yet been called for the current navigation.
   std::vector<blink::mojom::FaviconURL> favicon_urls() const {
diff --git a/components/google/core/common/google_util.cc b/components/google/core/common/google_util.cc
index 19db3d0..9789be38 100644
--- a/components/google/core/common/google_util.cc
+++ b/components/google/core/common/google_util.cc
@@ -343,4 +343,42 @@
   return *kGoogleRegisterableDomains;
 }
 
+GURL AppendToAsyncQueryParam(const GURL& url,
+                             const std::string& key,
+                             const std::string& value) {
+  const std::string param_name = "async";
+  const std::string key_value = key + ":" + value;
+  bool replaced = false;
+  const std::string input = url.query();
+  url::Component cursor(0, input.size());
+  std::string output;
+  url::Component key_range, value_range;
+  while (url::ExtractQueryKeyValue(input.data(), &cursor, &key_range,
+                                   &value_range)) {
+    const base::StringPiece key(input.data() + key_range.begin, key_range.len);
+    std::string key_value_pair(input, key_range.begin,
+                               value_range.end() - key_range.begin);
+    if (!replaced && key == param_name) {
+      // Check |replaced| as only the first match should be replaced.
+      replaced = true;
+      key_value_pair += "," + key_value;
+    }
+    if (!output.empty()) {
+      output += "&";
+    }
+
+    output += key_value_pair;
+  }
+  if (!replaced) {
+    if (!output.empty()) {
+      output += "&";
+    }
+
+    output += (param_name + "=" + key_value);
+  }
+  GURL::Replacements replacements;
+  replacements.SetQueryStr(output);
+  return url.ReplaceComponents(replacements);
+}
+
 }  // namespace google_util
diff --git a/components/google/core/common/google_util.h b/components/google/core/common/google_util.h
index e84acb5b..5642e29 100644
--- a/components/google/core/common/google_util.h
+++ b/components/google/core/common/google_util.h
@@ -115,6 +115,19 @@
 // unregistering themselves.
 const std::vector<std::string>& GetGoogleRegistrableDomains();
 
+// Appends the provided |key| and |value| pair to the "async" query param list,
+// according to the format used by the Google servers:
+//
+//   "async=<other key>:<other value>,<key>:<value>"
+//
+// If |url| does not have an "async" query param list it will be added.
+// Derived from net::AppendOrReplaceQueryParameter, that can't be used because
+// it escapes ":" to "%3A", but the servers requires the colon not to be
+// escaped. See: http://crbug.com/413845.
+GURL AppendToAsyncQueryParam(const GURL& url,
+                             const std::string& key,
+                             const std::string& value);
+
 }  // namespace google_util
 
 #endif  // COMPONENTS_GOOGLE_CORE_COMMON_GOOGLE_UTIL_H_
diff --git a/components/google/core/common/google_util_unittest.cc b/components/google/core/common/google_util_unittest.cc
index d0df418..4e1079a 100644
--- a/components/google/core/common/google_util_unittest.cc
+++ b/components/google/core/common/google_util_unittest.cc
@@ -469,3 +469,20 @@
       GURL("https://daily0-myapi-pa.sandbox.googleapis.com/v1/"
            "myservice?k1=v1&k2=v2")));
 }
+
+TEST(GoogleUtilTest, AppendToAsyncQueryParam) {
+  // Append to plain URL.
+  EXPECT_EQ(GURL("https://foo.com?async=bar:baz"),
+            google_util::AppendToAsyncQueryParam(GURL("https://foo.com"), "bar",
+                                                 "baz"));
+
+  // Append to async param.
+  EXPECT_EQ(GURL("https://foo.com?async=bar:baz,hello:world"),
+            google_util::AppendToAsyncQueryParam(
+                GURL("https://foo.com?async=bar:baz"), "hello", "world"));
+
+  // Append to same async param.
+  EXPECT_EQ(GURL("https://foo.com?async=bar:baz,bar:buz"),
+            google_util::AppendToAsyncQueryParam(
+                GURL("https://foo.com?async=bar:baz"), "bar", "buz"));
+}
diff --git a/components/history/content/browser/web_contents_top_sites_observer.cc b/components/history/content/browser/web_contents_top_sites_observer.cc
index 2945d43d..526a642 100644
--- a/components/history/content/browser/web_contents_top_sites_observer.cc
+++ b/components/history/content/browser/web_contents_top_sites_observer.cc
@@ -12,18 +12,6 @@
 
 namespace history {
 
-// static
-void WebContentsTopSitesObserver::CreateForWebContents(
-    content::WebContents* web_contents,
-    TopSites* top_sites) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new WebContentsTopSitesObserver(
-                                  web_contents, top_sites)));
-  }
-}
-
 WebContentsTopSitesObserver::WebContentsTopSitesObserver(
     content::WebContents* web_contents,
     TopSites* top_sites)
diff --git a/components/history/content/browser/web_contents_top_sites_observer.h b/components/history/content/browser/web_contents_top_sites_observer.h
index 4f9c840..9532912 100644
--- a/components/history/content/browser/web_contents_top_sites_observer.h
+++ b/components/history/content/browser/web_contents_top_sites_observer.h
@@ -21,9 +21,6 @@
  public:
   ~WebContentsTopSitesObserver() override;
 
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   TopSites* top_sites);
-
  private:
   friend class content::WebContentsUserData<WebContentsTopSitesObserver>;
 
diff --git a/components/javascript_dialogs/tab_modal_dialog_manager.cc b/components/javascript_dialogs/tab_modal_dialog_manager.cc
index 6499696..e4f89656 100644
--- a/components/javascript_dialogs/tab_modal_dialog_manager.cc
+++ b/components/javascript_dialogs/tab_modal_dialog_manager.cc
@@ -111,17 +111,6 @@
 
 }  // namespace
 
-// static
-void TabModalDialogManager::CreateForWebContents(
-    content::WebContents* web_contents,
-    std::unique_ptr<TabModalDialogManagerDelegate> delegate) {
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new TabModalDialogManager(
-                                  web_contents, std::move(delegate))));
-  }
-}
-
 TabModalDialogManager::~TabModalDialogManager() {
   CloseDialog(DismissalCause::kTabHelperDestroyed, false, base::string16());
 }
diff --git a/components/javascript_dialogs/tab_modal_dialog_manager.h b/components/javascript_dialogs/tab_modal_dialog_manager.h
index 2333a045..d91bf569 100644
--- a/components/javascript_dialogs/tab_modal_dialog_manager.h
+++ b/components/javascript_dialogs/tab_modal_dialog_manager.h
@@ -91,10 +91,6 @@
     kMaxValue = kDialogClosed,
   };
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      std::unique_ptr<TabModalDialogManagerDelegate> delegate);
-
   ~TabModalDialogManager() override;
 
   void BrowserActiveStateChanged();
@@ -133,10 +129,6 @@
  private:
   friend class content::WebContentsUserData<TabModalDialogManager>;
 
-  // This is here to hide the normal WebContentsUserData factory function in
-  // favor of that which takes a delegate.
-  static void CreateForWebContents(content::WebContents* web_contents);
-
   TabModalDialogManager(
       content::WebContents* web_contents,
       std::unique_ptr<TabModalDialogManagerDelegate> delegate);
diff --git a/components/media_router/common/media_source.cc b/components/media_router/common/media_source.cc
index 2f4b560..407f5266 100644
--- a/components/media_router/common/media_source.cc
+++ b/components/media_router/common/media_source.cc
@@ -54,6 +54,13 @@
   return url.is_valid() && IsSchemeAllowed(url);
 }
 
+bool IsValidStandardPresentationSource(const std::string& media_source) {
+  const GURL source_url(media_source);
+  return source_url.is_valid() && source_url.SchemeIsHTTPOrHTTPS() &&
+         !base::StartsWith(source_url.spec(), kLegacyCastPresentationUrlPrefix,
+                           base::CompareCase::INSENSITIVE_ASCII);
+}
+
 bool IsAutoJoinPresentationId(const std::string& presentation_id) {
   return presentation_id == kAutoJoinPresentationId;
 }
diff --git a/components/media_router/common/media_source.h b/components/media_router/common/media_source.h
index 61b55df8..2abc3648 100644
--- a/components/media_router/common/media_source.h
+++ b/components/media_router/common/media_source.h
@@ -45,6 +45,9 @@
 // Returns true if |url| is a valid presentation URL.
 bool IsValidPresentationUrl(const GURL& url);
 
+// Returns true if |media_source| has a valid presentation URL.
+bool IsValidStandardPresentationSource(const std::string& media_source);
+
 // Returns true if |presentation_id| is an ID used by auto-join requests.
 bool IsAutoJoinPresentationId(const std::string& presentation_id);
 
diff --git a/components/omnibox/browser/autocomplete_match_android.cc b/components/omnibox/browser/autocomplete_match_android.cc
index 48670edc..5461cda5 100644
--- a/components/omnibox/browser/autocomplete_match_android.cc
+++ b/components/omnibox/browser/autocomplete_match_android.cc
@@ -93,9 +93,8 @@
       ToJavaIntArray(env, description_class_styles), janswer,
       ConvertUTF16ToJavaString(env, fill_into_edit),
       url::GURLAndroid::FromNativeGURL(env, destination_url),
-      url::GURLAndroid::FromNativeGURL(env, destination_url),
-      j_image_dominant_color, SupportsDeletion(), j_post_content_type,
-      j_post_content,
+      url::GURLAndroid::FromNativeGURL(env, image_url), j_image_dominant_color,
+      SupportsDeletion(), j_post_content_type, j_post_content,
       suggestion_group_id.value_or(
           SearchSuggestionParser::kNoSuggestionGroupId),
       j_query_tiles, ToJavaByteArray(env, clipboard_image_data), has_tab_match,
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
index c5dc483..b0cb261 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -358,8 +358,11 @@
      * Whether to show a 'Details' link to the connection info popup.
      */
     private boolean isConnectionDetailsLinkVisible() {
+        // If Paint Preview is being shown, it completely obstructs the WebContents and users
+        // cannot interact with it. Hence, showing connection details is not relevant.
         return mContentPublisher == null && !mDelegate.isShowingOfflinePage()
-                && !mDelegate.isShowingPreview() && !mIsInternalPage;
+                && !mDelegate.isShowingPreview() && !mDelegate.isShowingPaintPreviewPage()
+                && !mIsInternalPage;
     }
 
     /**
@@ -403,6 +406,8 @@
         if (mContentPublisher != null) {
             messageBuilder.append(
                     mContext.getString(R.string.page_info_domain_hidden, mContentPublisher));
+        } else if (mDelegate.isShowingPaintPreviewPage()) {
+            messageBuilder.append(mDelegate.getPaintPreviewPageConnectionMessage());
         } else if (mDelegate.isShowingPreview() && mDelegate.isPreviewPageInsecure()) {
             connectionInfoParams.summary = summary;
         } else if (mDelegate.getOfflinePageConnectionMessage() != null) {
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java
index 344cb665..9afdd7a 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java
@@ -163,6 +163,13 @@
     }
 
     /**
+     * Whether the page being shown is a paint preview.
+     */
+    public boolean isShowingPaintPreviewPage() {
+        return false;
+    }
+
+    /**
      * Initialize viewParams with Offline Page UI info, if any.
      * @param viewParams The PageInfoViewParams to set state on.
      * @param runAfterDismiss Used to set "open Online" button callback for offline page.
@@ -182,6 +189,15 @@
     }
 
     /**
+     * Return the connection message shown for a paint preview page, if appropriate.
+     * Returns null if there's no paint preview page.
+     */
+    @Nullable
+    public String getPaintPreviewPageConnectionMessage() {
+        return null;
+    }
+
+    /**
      * Returns whether or not the performance badge should be shown for |url|.
      */
     public boolean shouldShowPerformanceBadge(String url) {
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.cc b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
index e49c1ea..efb9c69 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_factory.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
@@ -26,27 +26,6 @@
 
 namespace password_manager {
 
-namespace {
-
-const char kContentPasswordManagerDriverFactoryWebContentsUserDataKey[] =
-    "web_contents_password_manager_driver_factory";
-
-}  // namespace
-
-void ContentPasswordManagerDriverFactory::CreateForWebContents(
-    content::WebContents* web_contents,
-    PasswordManagerClient* password_client,
-    autofill::AutofillClient* autofill_client) {
-  if (FromWebContents(web_contents))
-    return;
-
-  // NOTE: Can't use |std::make_unique| due to private constructor.
-  web_contents->SetUserData(
-      kContentPasswordManagerDriverFactoryWebContentsUserDataKey,
-      base::WrapUnique(new ContentPasswordManagerDriverFactory(
-          web_contents, password_client, autofill_client)));
-}
-
 ContentPasswordManagerDriverFactory::ContentPasswordManagerDriverFactory(
     content::WebContents* web_contents,
     PasswordManagerClient* password_client,
@@ -59,15 +38,6 @@
     default;
 
 // static
-ContentPasswordManagerDriverFactory*
-ContentPasswordManagerDriverFactory::FromWebContents(
-    content::WebContents* contents) {
-  return static_cast<ContentPasswordManagerDriverFactory*>(
-      contents->GetUserData(
-          kContentPasswordManagerDriverFactoryWebContentsUserDataKey));
-}
-
-// static
 void ContentPasswordManagerDriverFactory::BindPasswordManagerDriver(
     mojo::PendingAssociatedReceiver<autofill::mojom::PasswordManagerDriver>
         pending_receiver,
@@ -136,4 +106,6 @@
     frame_and_driver.second.SendLoggingAvailability();
 }
 
+WEB_CONTENTS_USER_DATA_KEY_IMPL(ContentPasswordManagerDriverFactory)
+
 }  // namespace password_manager
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.h b/components/password_manager/content/browser/content_password_manager_driver_factory.h
index 9292611..73372cb5 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_factory.h
+++ b/components/password_manager/content/browser/content_password_manager_driver_factory.h
@@ -16,6 +16,7 @@
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 
@@ -31,16 +32,10 @@
 // factory per WebContents, and one driver per render frame.
 class ContentPasswordManagerDriverFactory
     : public content::WebContentsObserver,
-      public base::SupportsUserData::Data {
+      public content::WebContentsUserData<ContentPasswordManagerDriverFactory> {
  public:
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   PasswordManagerClient* client,
-                                   autofill::AutofillClient* autofill_client);
   ~ContentPasswordManagerDriverFactory() override;
 
-  static ContentPasswordManagerDriverFactory* FromWebContents(
-      content::WebContents* web_contents);
-
   static void BindPasswordManagerDriver(
       mojo::PendingAssociatedReceiver<autofill::mojom::PasswordManagerDriver>
           pending_receiver,
@@ -54,6 +49,9 @@
   void RequestSendLoggingAvailability();
 
  private:
+  friend class content::WebContentsUserData<
+      ContentPasswordManagerDriverFactory>;
+
   ContentPasswordManagerDriverFactory(
       content::WebContents* web_contents,
       PasswordManagerClient* client,
@@ -70,6 +68,8 @@
   PasswordManagerClient* password_client_;
   autofill::AutofillClient* autofill_client_;
 
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
   DISALLOW_COPY_AND_ASSIGN(ContentPasswordManagerDriverFactory);
 };
 
diff --git a/chrome/android/java/res/drawable/google_pay.xml b/components/payments/content/android/java/res/drawable/google_pay.xml
similarity index 100%
rename from chrome/android/java/res/drawable/google_pay.xml
rename to components/payments/content/android/java/res/drawable/google_pay.xml
diff --git a/components/payments/content/android/payments_java_resources.gni b/components/payments/content/android/payments_java_resources.gni
index 4d9a4a6..c7a2bd5 100644
--- a/components/payments/content/android/payments_java_resources.gni
+++ b/components/payments/content/android/payments_java_resources.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 payments_java_resources = [
+  "//components/payments/content/android/java/res/drawable/google_pay.xml",
   "//components/payments/content/android/java/res/layout/payment_handler_content.xml",
   "//components/payments/content/android/java/res/layout/payment_minimal_ui_content.xml",
   "//components/payments/content/android/java/res/layout/payment_minimal_ui_toolbar.xml",
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn
index b4c03203..7412619 100644
--- a/components/policy/BUILD.gn
+++ b/components/policy/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/chrome_build.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/mac/base_rules.gni")
 import("//build/config/python.gni")
@@ -23,7 +24,7 @@
 gen_policy_templates_linux = is_linux || is_chromeos
 gen_policy_templates_android = is_android
 gen_policy_templates_mac = is_mac
-gen_policy_templates_chromeos = is_chromeos
+gen_policy_templates_chromeos = is_chromeos_ash
 gen_policy_templates_ios = is_ios
 
 # The zip file is grabbed from the Windows build right now.
diff --git a/components/policy/core/browser/BUILD.gn b/components/policy/core/browser/BUILD.gn
index d56d4eb3..f33b4c6 100644
--- a/components/policy/core/browser/BUILD.gn
+++ b/components/policy/core/browser/BUILD.gn
@@ -49,6 +49,7 @@
   deps = [
     "//base/third_party/dynamic_annotations",
     "//build:branding_buildflags",
+    "//build:chromeos_buildflags",
     "//components/google/core/common",
     "//components/keyed_service/core",
     "//components/pref_registry",
@@ -99,6 +100,7 @@
   ]
   deps = [
     "//build:branding_buildflags",
+    "//build:chromeos_buildflags",
     "//components/prefs",
     "//testing/gtest",
     "//url",
diff --git a/components/policy/core/browser/policy_conversions.cc b/components/policy/core/browser/policy_conversions.cc
index 4ef4c2e4..6dbe7ed 100644
--- a/components/policy/core/browser/policy_conversions.cc
+++ b/components/policy/core/browser/policy_conversions.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/check.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/browser/policy_conversions_client.h"
 #include "components/strings/grit/components_strings.h"
 #include "extensions/buildflags/buildflags.h"
@@ -110,22 +111,22 @@
     all_policies.SetKey("updaterPolicies", client()->GetUpdaterPolicies());
 #endif
 
-#if BUILDFLAG(ENABLE_EXTENSIONS) && defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(IS_CHROMEOS_ASH)
   all_policies.SetKey("loginScreenExtensionPolicies",
                       GetExtensionPolicies(POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-#endif  //  BUILDFLAG(ENABLE_EXTENSIONS) && defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   all_policies.SetKey("deviceLocalAccountPolicies",
                       GetDeviceLocalAccountPolicies());
   Value identity_fields = client()->GetIdentityFields();
   if (!identity_fields.is_none())
     all_policies.MergeDictionary(&identity_fields);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   return all_policies;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 Value DictionaryPolicyConversions::GetDeviceLocalAccountPolicies() {
   Value policies = client()->GetDeviceLocalAccountPolicies();
   Value device_values(Value::Type::DICTIONARY);
@@ -176,16 +177,16 @@
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
   }
 
-#if BUILDFLAG(ENABLE_EXTENSIONS) && defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(IS_CHROMEOS_ASH)
   for (auto& policy :
        client()
            ->GetExtensionPolicies(POLICY_DOMAIN_SIGNIN_EXTENSIONS)
            .TakeList()) {
     all_policies.Append(std::move(policy));
   }
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS) && defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   for (auto& device_policy :
        client()->GetDeviceLocalAccountPolicies().TakeList())
     all_policies.Append(std::move(device_policy));
@@ -193,7 +194,7 @@
   Value identity_fields = client()->GetIdentityFields();
   if (!identity_fields.is_none())
     all_policies.Append(std::move(identity_fields));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   return all_policies;
 }
diff --git a/components/policy/core/browser/policy_conversions.h b/components/policy/core/browser/policy_conversions.h
index 9890d922..7ef0f63 100644
--- a/components/policy/core/browser/policy_conversions.h
+++ b/components/policy/core/browser/policy_conversions.h
@@ -12,6 +12,7 @@
 #include "base/values.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_namespace.h"
 #include "components/policy/core/common/policy_types.h"
@@ -93,7 +94,7 @@
  private:
   base::Value GetExtensionPolicies(PolicyDomain policy_domain);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   base::Value GetDeviceLocalAccountPolicies();
 #endif
 
diff --git a/components/policy/core/browser/policy_conversions_client.h b/components/policy/core/browser/policy_conversions_client.h
index e87af33..932fd02 100644
--- a/components/policy/core/browser/policy_conversions_client.h
+++ b/components/policy/core/browser/policy_conversions_client.h
@@ -13,6 +13,7 @@
 #include "base/values.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/browser/policy_conversions.h"
 #include "components/policy/core/common/schema.h"
 #include "components/policy/policy_export.h"
@@ -86,7 +87,7 @@
   // Returns policies for Chrome extensions.
   virtual base::Value GetExtensionPolicies(PolicyDomain policy_domain) = 0;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Returns policies for ChromeOS device.
   virtual base::Value GetDeviceLocalAccountPolicies() = 0;
   // Returns device specific information if this device is enterprise managed.
diff --git a/components/policy/core/browser/policy_pref_mapping_test.cc b/components/policy/core/browser/policy_pref_mapping_test.cc
index 5b9226b1..915ec95 100644
--- a/components/policy/core/browser/policy_pref_mapping_test.cc
+++ b/components/policy/core/browser/policy_pref_mapping_test.cc
@@ -20,6 +20,7 @@
 #include "base/values.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/schema.h"
 #include "components/policy/policy_constants.h"
@@ -280,9 +281,9 @@
     const std::string os("ios");
 #elif defined(OS_APPLE)
     const std::string os("mac");
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
     const std::string os("chromeos");
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
     const std::string os("linux");
 #else
 #error "Unknown platform"
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn
index 5d715b2..ba65baa8 100644
--- a/components/policy/core/common/BUILD.gn
+++ b/components/policy/core/common/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
@@ -170,6 +171,7 @@
   deps = [
     "//base:i18n",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//components/account_id",
     "//components/enterprise/common:strings",
     "//components/prefs",
@@ -251,7 +253,7 @@
     ]
     deps += [ "//components/policy/android:jni_headers" ]
   }
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//chromeos/system" ]
     sources += [
       "policy_scheduler.cc",
@@ -338,7 +340,7 @@
     "remote_commands/testing_remote_commands_server.h",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources -= [
       "cloud/mock_user_cloud_policy_store.cc",
       "cloud/mock_user_cloud_policy_store.h",
@@ -372,11 +374,16 @@
     "//testing/gmock",
     "//testing/gtest",
   ]
+
+  deps = [ "//build:chromeos_buildflags" ]
 }
 
 source_set("common_constants") {
   configs += [ "//components/policy:component_implementation" ]
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+    "//build:chromeos_buildflags",
+  ]
   sources = [
     "../../policy_export.h",
     "cloud/cloud_policy_constants.cc",
@@ -433,7 +440,7 @@
       "registry_dict_unittest.cc",
     ]
   }
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "policy_scheduler_unittest.cc",
       "proxy_policy_provider_unittest.cc",
@@ -504,6 +511,7 @@
     ":test_support",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/account_id",
     "//components/policy:generated",
     "//components/prefs:test_support",
@@ -517,7 +525,7 @@
     "//third_party/libxml:xml_reader",
     "//ui/base",
   ]
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//chromeos/system" ]
   }
   if (is_android) {
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index 8f6282bb..a81ac7c 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/core/common/cloud/dm_auth.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
@@ -37,7 +38,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/fake_statistics_provider.h"
 #endif
 
@@ -80,7 +81,7 @@
 const char kEnrollmentId[] = "fake-enrollment-id";
 
 #if defined(OS_WIN) || defined(OS_APPLE) || \
-    defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 const char kEnrollmentToken[] = "enrollment_token";
 #endif
 
@@ -225,7 +226,7 @@
         ->set_device_management_token(kDMToken2);
 
 #if defined(OS_WIN) || defined(OS_APPLE) || \
-    defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
     em::RegisterBrowserRequest* enrollment_request =
         enrollment_token_request_.mutable_register_browser_request();
     enrollment_request->set_machine_name(policy::GetMachineName());
@@ -312,7 +313,7 @@
         robot_auth_code_fetch_response_.mutable_service_api_access_response();
     api_response->set_auth_code(kRobotAuthCode);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     fake_statistics_provider_.SetMachineStatistic(
         chromeos::system::kSerialNumberKeyForTest, "fake_serial_number");
 #endif
@@ -650,7 +651,7 @@
   std::unique_ptr<CloudPolicyClient> client_;
   network::TestURLLoaderFactory url_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
 #endif
 };
@@ -706,7 +707,7 @@
 }
 
 #if defined(OS_WIN) || defined(OS_APPLE) || \
-    defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 TEST_F(CloudPolicyClientTest, RegistrationWithTokenAndPolicyFetch) {
   ExpectEnrollmentTokenBasedRegistration();
   EXPECT_CALL(observer_, OnRegistrationStateChanged(_));
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.cc b/components/policy/core/common/cloud/cloud_policy_constants.cc
index 86f2e4d4..bea4aea 100644
--- a/components/policy/core/common/cloud/cloud_policy_constants.cc
+++ b/components/policy/core/common/cloud/cloud_policy_constants.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/policy_switches.h"
 
 namespace policy {
@@ -68,7 +69,7 @@
 const char kValueRequestCertProvisioningRequest[] = "client_cert_provisioning";
 
 const char kChromeDevicePolicyType[] = "google/chromeos/device";
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kChromeUserPolicyType[] = "google/chromeos/user";
 #elif defined(OS_ANDROID)
 const char kChromeUserPolicyType[] = "google/android/user";
diff --git a/components/policy/core/common/cloud/cloud_policy_util.cc b/components/policy/core/common/cloud/cloud_policy_util.cc
index 1153b71..c7902703 100644
--- a/components/policy/core/common/cloud/cloud_policy_util.cc
+++ b/components/policy/core/common/cloud/cloud_policy_util.cc
@@ -5,6 +5,7 @@
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 
 #if defined(OS_WIN)
@@ -17,7 +18,7 @@
 #include <wincred.h>
 #endif
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) || defined(OS_APPLE)
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || defined(OS_APPLE)
 #include <pwd.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -32,7 +33,9 @@
 #import <SystemConfiguration/SCDynamicStoreCopySpecific.h>
 #endif
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include <limits.h>  // For HOST_NAME_MAX
 #endif
 
@@ -47,7 +50,7 @@
 #endif
 #include "components/version_info/version_info.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/statistics_provider.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
@@ -66,7 +69,9 @@
 #include "base/system/sys_info.h"
 #endif
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "base/system/sys_info.h"
 #endif
 
@@ -75,7 +80,9 @@
 namespace em = enterprise_management;
 
 std::string GetMachineName() {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   char hostname[HOST_NAME_MAX];
   if (gethostname(hostname, HOST_NAME_MAX) == 0)  // Success.
     return hostname;
@@ -159,7 +166,7 @@
 }
 
 std::string GetOSUsername() {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) || defined(OS_APPLE)
+#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || defined(OS_APPLE)
   struct passwd* creds = getpwuid(getuid());
   if (!creds || !creds->pw_name)
     return std::string();
@@ -178,7 +185,7 @@
   }
 
   return base::WideToUTF8(username);
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   if (!user_manager::UserManager::IsInitialized())
     return std::string();
   auto* user = user_manager::UserManager::Get()->GetPrimaryUser();
@@ -207,7 +214,7 @@
 }
 
 std::string GetDeviceName() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   return chromeos::system::StatisticsProvider::GetInstance()
       ->GetEnterpriseMachineID();
 #else
diff --git a/components/policy/core/common/cloud/cloud_policy_validator_unittest.cc b/components/policy/core/common/cloud/cloud_policy_validator_unittest.cc
index 23b38f0e..0549ed9 100644
--- a/components/policy/core/common/cloud/cloud_policy_validator_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_validator_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/policy_builder.h"
 #include "components/policy/core/common/policy_switches.h"
@@ -402,7 +403,7 @@
   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Validation key is not currently checked on Chrome OS
 // (http://crbug.com/328038).
 TEST_F(CloudPolicyValidatorTest, ErrorInvalidPublicKeyVerificationSignature) {
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc
index 7074130f..a42d35c 100644
--- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc
+++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/core/common/cloud/dm_auth.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
@@ -17,7 +18,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/fake_statistics_provider.h"
 #endif
 
@@ -176,7 +177,7 @@
  public:
   EncryptedReportingJobConfigurationTest()
       : client_(&service_),
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
         fake_serial_number_(&fake_statistics_provider_),
 #endif
         configuration_(
@@ -248,7 +249,7 @@
   StrictMock<MockCallbackObserver> callback_observer_;
   DeviceManagementService::Job job_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
   class ScopedFakeSerialNumber {
    public:
diff --git a/components/policy/core/common/cloud/policy_builder.cc b/components/policy/core/common/cloud/policy_builder.cc
index af0f25a..09a7c74 100644
--- a/components/policy/core/common/cloud/policy_builder.cc
+++ b/components/policy/core/common/cloud/policy_builder.cc
@@ -6,6 +6,7 @@
 
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "crypto/signature_creator.h"
 
@@ -388,7 +389,7 @@
 template class TypedPolicyBuilder<em::ExternalPolicyData>;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 StringPolicyBuilder::StringPolicyBuilder() = default;
 
 void StringPolicyBuilder::Build() {
diff --git a/components/policy/core/common/cloud/policy_builder.h b/components/policy/core/common/cloud/policy_builder.h
index b589fb67..33063f86 100644
--- a/components/policy/core/common/cloud/policy_builder.h
+++ b/components/policy/core/common/cloud/policy_builder.h
@@ -15,6 +15,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/proto/cloud_policy.pb.h"
 #include "components/policy/proto/device_management_backend.pb.h"
@@ -204,7 +205,7 @@
     TypedPolicyBuilder<enterprise_management::ExternalPolicyData>;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 using ComponentActiveDirectoryPolicyBuilder = StringPolicyBuilder;
 #endif
 
diff --git a/components/policy/core/common/cloud/realtime_reporting_job_configuration_unittest.cc b/components/policy/core/common/cloud/realtime_reporting_job_configuration_unittest.cc
index e5963bc..036ff5d 100644
--- a/components/policy/core/common/cloud/realtime_reporting_job_configuration_unittest.cc
+++ b/components/policy/core/common/cloud/realtime_reporting_job_configuration_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
@@ -23,7 +24,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/system/fake_statistics_provider.h"
 #endif
 
@@ -65,7 +66,7 @@
 class RealtimeReportingJobConfigurationTest : public testing::Test {
  public:
   RealtimeReportingJobConfigurationTest()
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       : client_(&service_),
         fake_serial_number_(&fake_statistics_provider_)
 #else
@@ -155,7 +156,7 @@
   MockCloudPolicyClient client_;
   StrictMock<MockCallbackObserver> callback_observer_;
   DeviceManagementService::Job job_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
   class ScopedFakeSerialNumber {
    public:
diff --git a/components/policy/core/common/generate_policy_source_unittest.cc b/components/policy/core/common/generate_policy_source_unittest.cc
index d7c75da..c0b8fd5 100644
--- a/components/policy/core/common/generate_policy_source_unittest.cc
+++ b/components/policy/core/common/generate_policy_source_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/policy_details.h"
 #include "components/policy/core/common/schema.h"
 #include "components/policy/policy_constants.h"
@@ -20,7 +21,7 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Checks if two schemas are the same or not. Note that this function doesn't
 // consider restrictions on integers and strings nor pattern properties.
 bool IsSameSchema(Schema a, Schema b) {
@@ -154,7 +155,7 @@
   ASSERT_EQ(base::Value::Type::STRING, subschema.type());
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   subschema = schema.GetKnownProperty(key::kPowerManagementIdleSettings);
   ASSERT_TRUE(subschema.valid());
 
@@ -193,7 +194,7 @@
   EXPECT_EQ(0u, details->max_external_data_size);
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   details = GetChromePolicyDetails(key::kDevicePolicyRefreshRate);
   ASSERT_TRUE(details);
   EXPECT_FALSE(details->is_deprecated);
@@ -206,7 +207,7 @@
   // than 0, once a type 'external' policy is added.
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST(GeneratePolicySource, SetEnterpriseDefaults) {
   PolicyMap policy_map;
 
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc
index 2a2797e..42d6adf 100644
--- a/components/policy/core/common/policy_service_impl.cc
+++ b/components/policy/core/common/policy_service_impl.cc
@@ -19,6 +19,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/features.h"
 #include "components/policy/core/common/policy_bundle.h"
 #include "components/policy/core/common/policy_map.h"
@@ -113,7 +114,7 @@
       {policy::key::kNativeMessagingWhitelist,
        policy::key::kNativeMessagingAllowlist},
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       {policy::key::kAttestationExtensionWhitelist,
        policy::key::kAttestationExtensionAllowlist},
       {policy::key::kExternalPrintServersWhitelist,
@@ -132,7 +133,7 @@
       {policy::key::kPrintingAPIExtensionsWhitelist,
        policy::key::kPrintingAPIExtensionsAllowlist},
 #endif  // defined(USE_CUPS)
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }};
   for (const auto& policy_pair : renamed_policies) {
     PolicyMap::Entry* old_policy = policies->GetMutable(policy_pair.first);
diff --git a/components/policy/proto/BUILD.gn b/components/policy/proto/BUILD.gn
index c2738ea..72600eb 100644
--- a/components/policy/proto/BUILD.gn
+++ b/components/policy/proto/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 import("//third_party/protobuf/proto_library.gni")
 
@@ -61,7 +62,7 @@
     "policy_signing_key.proto",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "chrome_device_policy.proto",
       "install_attributes.proto",
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index ea922e9..b67d1b2 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -457,6 +457,7 @@
         'AuthAndroidNegotiateAccountType',
         'AllowCrossOriginAuthPrompt',
         'NtlmV2Enabled',
+        'IntegratedWebAuthenticationAllowed',
       ],
     },
     {
@@ -5082,7 +5083,7 @@
         },
         {
           'value': None,
-          'caption': 'Allow 3rd party cookes, but allow the user to change this setting',
+          'caption': 'Allow 3rd party cookies, but allow the user to change this setting',
         },
       ],
       'example_value': False,
@@ -11874,13 +11875,13 @@
 
       * A warning dialog appears if the user remains idle for the time specified by <ph name="IDLE_WARNING_FIELD_NAME">IdleWarning</ph>. It warns the user that the idle action will be taken and only appears if the idle action is to sign out or shut down.
 
-      * The action specified by <ph name="IDLE_ACTION_FIELD_NAME">IdleAction</ph> is taken if the user is idle for the time specified by Idle.
+      * The action specified by <ph name="IDLE_ACTION_FIELD_NAME">IdleAction</ph> is taken if the user is idle for the time specified by <ph name="IDLE_FIELD_NAME">Idle</ph>.
 
       For each of the above actions, the delay should be specified in milliseconds and must be set to a value greater than zero to trigger the corresponding action. If the delay is set to zero, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> won't take the corresponding action.
 
       For each of the above delays, when the time is unset, a default value is used.
 
-      <ph name="SCREEN_DIM_FIELD_NAME">ScreenDim</ph> values will be clamped to be less than or equal to <ph name="SCREEN_OFF_FIELD_NAME">ScreenOff</ph>. <ph name="SCREEN_OFF_FIELD_NAME">ScreenOff</ph> and <ph name="IDLE_WARNING_FIELD_NAME">IdleWarning</ph> will be clamped to be less than or equal to Idle.
+      <ph name="SCREEN_DIM_FIELD_NAME">ScreenDim</ph> values will be clamped to be less than or equal to <ph name="SCREEN_OFF_FIELD_NAME">ScreenOff</ph>. <ph name="SCREEN_OFF_FIELD_NAME">ScreenOff</ph> and <ph name="IDLE_WARNING_FIELD_NAME">IdleWarning</ph> will be clamped to be less than or equal to <ph name="IDLE_FIELD_NAME">Idle</ph>.
 
       <ph name="IDLE_ACTION_FIELD_NAME">IdleAction</ph> can be one of 4 actions:
 
@@ -16312,13 +16313,17 @@
       'id': 784,
       'caption': '''Configure allowed quick unlock modes''',
       'tags': [],
-      'desc': '''The policy controls a list of quick unlock modes that users can configure and use to unlock the lock screen.
+      'desc': '''Setting the policy controls which quick unlock modes can unlock the lock screen.
 
-          This value is a list of strings; valid list entries are: "all", "PIN", "FINGERPRINT". Adding "all" to the list means that every quick unlock mode is available to the user, including ones implemented in the future. Otherwise, only the quick unlock modes present in the list will be available.
+      To allow:
 
-          For example, to allow every quick unlock mode, use ["all"]. To allow only PIN unlock, use ["PIN"]. To allow PIN and fingerprint, use ["PIN", "FINGERPRINT"].
+      * Every quick unlock mode, use ["all"] (includes modes added in the future).
 
-          If the policy is not set or set to an empty list, no quick unlock modes are available for managed devices''',
+      * Only PIN unlock, use ["PIN"].
+
+      * PIN and fingerprint, use ["PIN", "FINGERPRINT"].
+
+      If the policy is unset or set to an empty list, no quick unlock modes are available for managed devices.''',
     },
     {
       'name': 'QuickUnlockModeWhitelist',
@@ -16347,15 +16352,19 @@
       'id': 352,
       'caption': '''Configure allowed quick unlock modes''',
       'tags': [],
-      'desc': '''The policy controls a list of quick unlock modes that users can configure and use to unlock the lock screen.
+      'desc': '''Setting the policy controls which quick unlock modes can unlock the lock screen.
 
-          This value is a list of strings; valid list entries are: "all", "PIN", "FINGERPRINT". Adding "all" to the list means that every quick unlock mode is available to the user, including ones implemented in the future. Otherwise, only the quick unlock modes present in the list will be available.
+      To allow:
 
-          For example, to allow every quick unlock mode, use ["all"]. To allow only PIN unlock, use ["PIN"]. To allow PIN and fingerprint, use ["PIN", "FINGERPRINT"].
+      * Every quick unlock mode, use ["all"] (includes modes added in the future).
 
-          If the policy is not set or set to an empty list, no quick unlock modes are available for managed devices
+      * Only PIN unlock, use ["PIN"].
 
-          This policy is deprecated, please use <ph name="QUICK_UNLOCK_MODE_ALLOW_LIST_POLICY_NAME">QuickUnlockModeAllowlist</ph> instead=''',
+      * PIN and fingerprint, use ["PIN", "FINGERPRINT"].
+
+      If the policy is unset or set to an empty list, no quick unlock modes are available for managed devices.
+
+      This policy is deprecated, please use <ph name="QUICK_UNLOCK_MODE_ALLOW_LIST_POLICY_NAME">QuickUnlockModeAllowlist</ph> instead''',
     },
     {
       'name': 'QuickUnlockTimeout',
@@ -16396,11 +16405,9 @@
       'id': 353,
       'caption': '''Set how often user has to enter password to use quick unlock''',
       'tags': [],
-      'desc': '''This setting controls how often the lock screen will request the password to be entered in order to continue using quick unlock. Each time the lock screen is entered, if the last password entry was more than this setting, the quick unlock will not be available on entering the lock screen. Should the user stay on the lock screen past this period of time, a password will be requested next time the user enters the wrong code, or re-enters the lock screen, whichever comes first.
+      'desc': '''Setting the policy controls how often the lock screen requests the password for quick unlock. Each time the lock screen appears, if the last password entry occured before the time window specified by the value chosen, quick unlock won't be available. If users stay on the lock screen past this amount of time, a password is requested next time they enter the wrong code or re-enter the lock screen, whichever comes first.
 
-          If this setting is configured, users using quick unlock will be requested to enter their passwords on the lock screen depending on this setting.
-
-          If this setting is not configured, users using quick unlock will be requested to enter their password on the lock screen every day.''',
+      Leaving the policy unset means users using quick unlock enter their password on the lock screen daily.''',
     },
     {
       'name': 'PinUnlockMinimumLength',
@@ -16416,12 +16423,9 @@
       'id': 354,
       'caption': '''Set the minimum length of the lock screen PIN''',
       'tags': [],
-      'desc': '''If the policy is set, the configured minimal PIN length is
-          enforced. (The absolute minimum PIN length is 1; values less than 1
-          are treated as 1.)
+      'desc': '''Setting the policy enforces the minimum PIN length chosen. (Values below 1 are rounded up to the minimum of 1.)
 
-          If the policy is not set, a minimal PIN length of 6 digits is
-          enforced. This is the recommended minimum.''',
+      Leaving the policy unset enforces a minimal PIN length of 6 digits, the recommended minimum.''',
     },
     {
       'name': 'PinUnlockMaximumLength',
@@ -16437,9 +16441,9 @@
       'id': 355,
       'caption': '''Set the maximum length of the lock screen PIN''',
       'tags': [],
-      'desc': '''If the policy is set, the configured maximal PIN length is enforced. A value of 0 or less means no maximum length; in that case the user may set a PIN as long as they want. If this setting is less than <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME">PinUnlockMinimumLength</ph> but greater than 0, the maximum length is the same as the minimum length.
+      'desc': '''Setting the policy means the configured maximum PIN length is enforced. A value of 0 or less means the user may set a PIN of any length. If the value is less than <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME">PinUnlockMinimumLength</ph> but greater than 0, the maximum length is set to the minimum length.
 
-          If the policy is not set, no maximum length is enforced.''',
+      Leaving the policy unset means no maximum length is enforced.''',
     },
     {
       'name': 'PinUnlockWeakPinsAllowed',
@@ -16455,11 +16459,9 @@
       'id': 356,
       'caption': '''Enable users to set weak PINs for the lock screen PIN''',
       'tags': [],
-      'desc': '''If false, users will be unable to set PINs which are weak and easy to guess.
+      'desc': '''Setting the policy to Enabled allows weak PINs. Some characteristics of weak PINs: only one digit (1111), digits increase by 1 (1234), digits decrease by 1 (4321), and common PINs. Setting the policy to Disabled means users can't set weak, easy-to-guess PINs.
 
-          Some example weak PINs: PINs containing only one digit (1111), PINs whose digits are increasing by 1 (1234), PINs whose digits are decreasing by 1 (4321), and PINs which are commonly used.
-
-          By default, users will get a warning, not error, if the PIN is considered weak.''',
+      By default, users get a warning, not an error, for a weak PIN.''',
     },
     {
       'name': 'DeviceWallpaperImage',
@@ -20428,7 +20430,7 @@
       'id': 538,
       'caption': '''Enable peak shift power management''',
       'tags': [],
-      'desc': '''Setting the policy to Enabled and setting <ph name="DEVICE_POWER_PEAK_SHIFT_BATTERY_THRESHOLD_POLICY_NAME">DevicePowerPeakShiftBatteryThreshold</ph> and <ph name="DEVICE_POWER_PEAK_SHIFT_DAY_CONFIG_POLICY_NAME">DevicePowerPeakShiftDayConfig</ph> keeps power peak shift on, if supported on the device. Power peak shift power management policy is a power-saving policy that minimizes alternating current usage during peak times. For each weekday, you can set a start and end time to run in power peak shift mode. As long as the battery stays above the threshold specified, during these times, the device runs from the battery (even if the alternating current is attached). After the specified end time, the device runs from alternating current (if attached), but won't charge the battery. The device will again function normally using alternating current and recharging the battery after the specified start time.
+      'desc': '''Setting the policy to Enabled and setting <ph name="DEVICE_POWER_PEAK_SHIFT_BATTERY_THRESHOLD_POLICY_NAME">DevicePowerPeakShiftBatteryThreshold</ph> and <ph name="DEVICE_POWER_PEAK_SHIFT_DAY_CONFIG_POLICY_NAME">DevicePowerPeakShiftDayConfig</ph> keeps power peak shift on, if supported on the device. Power peak shift power management policy is a power-saving policy that minimizes alternating current usage during peak times. For each weekday, you can set a start and end time to run in power peak shift mode. As long as the battery stays above the threshold specified, during these times, the device runs from the battery (even if the alternating current is attached). After the specified end time, the device runs from alternating current (if attached), but won't charge the battery. The device will again function normally using alternating current and recharging the battery after the specified charge start time.
 
       Setting the policy to Disabled keeps power peak shift off.
 
@@ -23857,6 +23859,37 @@
 
       If this policy is set to Enabled, the user can use the <ph name="LACROS_NAME">Lacros</ph> browser.''',
     },
+    {
+      'name': 'IntegratedWebAuthenticationAllowed',
+      'owners': ['acostinas@chromium.org', 'pmarko@chromium.org'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_os:89-'],
+      'features': {
+        'dynamic_refresh': False,
+        'per_profile': False,
+      },
+      'items': [
+        {
+          'value': True,
+          'caption': 'The <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials will be used for network authentication to a managed proxy.',
+        },
+        {
+          'value': False,
+          'caption': 'The <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials will not be used for network authentication.',
+        },
+      ],
+      'example_value': True,
+      'id': 808,
+      'default': False,
+      'caption': '''Allow reusing the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials for network authentication''',
+      'tags': [],
+      'desc': '''This setting allows users to authenticate to a managed proxy secured with NTLM authentication using the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials.
+
+      If this policy is set to False or unset, the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials will not be used for network authentication.
+
+      If this policy is set to True, the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials will be used for network authentication to a managed proxy. In case the authentication with the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> login credentials fails, the user will be prompted for credentials.''',
+    },
   ],
 
   'messages': {
@@ -24779,6 +24812,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 807,
+  'highest_id_currently_used': 808,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/components/safe_browsing/content/password_protection/BUILD.gn b/components/safe_browsing/content/password_protection/BUILD.gn
index 58233dc..df331e4 100644
--- a/components/safe_browsing/content/password_protection/BUILD.gn
+++ b/components/safe_browsing/content/password_protection/BUILD.gn
@@ -14,6 +14,8 @@
       "password_protection_request.h",
       "password_protection_service.cc",
       "password_protection_service.h",
+      "request_canceler_content.cc",
+      "request_canceler_content.h",
     ]
 
     public_deps = [ "//google_apis:google_apis" ]
@@ -36,6 +38,7 @@
       "//components/safe_browsing/core/db:allowlist_checker_client",
       "//components/safe_browsing/core/db:database_manager",
       "//components/safe_browsing/core/db:v4_protocol_manager_util",
+      "//components/safe_browsing/core/password_protection",
       "//components/safe_browsing/core/password_protection:password_protection_metrics_util",
       "//components/sessions",
       "//components/signin/public/base",
diff --git a/components/safe_browsing/content/password_protection/password_protection_request.cc b/components/safe_browsing/content/password_protection/password_protection_request.cc
index 23daf863..aa728ce 100644
--- a/components/safe_browsing/content/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/content/password_protection/password_protection_request.cc
@@ -96,6 +96,15 @@
   return base::flat_set<std::string>(std::move(matching_domains)).extract();
 }
 
+bool IsClientSideDetectionEnabled() {
+#if BUILDFLAG(FULL_SAFE_BROWSING)
+  return true;
+#else
+  return base::FeatureList::IsEnabled(
+      safe_browsing::kClientSideDetectionForAndroid);
+#endif
+}
+
 }  // namespace
 
 PasswordProtectionRequest::PasswordProtectionRequest(
@@ -112,8 +121,7 @@
     bool password_field_exists,
     PasswordProtectionService* pps,
     int request_timeout_in_ms)
-    : content::WebContentsObserver(web_contents),
-      web_contents_(web_contents),
+    : web_contents_(web_contents),
       main_frame_url_(main_frame_url),
       password_form_action_(password_form_action),
       password_form_frame_url_(password_form_frame_url),
@@ -138,6 +146,9 @@
   request_proto_->set_trigger_type(trigger_type_);
   *request_proto_->mutable_url_display_experiment() =
       pps->GetUrlDisplayExperiment();
+
+  request_canceler_ =
+      RequestCanceler::CreateRequestCanceler(GetWeakPtr(), web_contents);
 }
 
 PasswordProtectionRequest::~PasswordProtectionRequest() {
@@ -328,20 +339,15 @@
       NOTREACHED();
   }
 
-  bool client_side_detection_enabled =
-#if BUILDFLAG(FULL_SAFE_BROWSING)
-      true;
-#else
-      base::FeatureList::IsEnabled(
-          safe_browsing::kClientSideDetectionForAndroid);
-#endif
-
-  if (!client_side_detection_enabled) {
+  if (IsClientSideDetectionEnabled()) {
+    GetDomFeatures();
+  } else {
     SendRequest();
-    return;
   }
+}
 
-  // Get the page DOM features.
+#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
+void PasswordProtectionRequest::GetDomFeatures() {
   content::RenderFrameHost* rfh = web_contents_->GetMainFrame();
   password_protection_service_->GetPhishingDetector(rfh->GetRemoteInterfaces(),
                                                     &phishing_detector_);
@@ -358,7 +364,6 @@
   dom_feature_start_time_ = base::TimeTicks::Now();
 }
 
-#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
 void PasswordProtectionRequest::OnGetDomFeatures(
     mojom::PhishingDetectorResult result,
     const std::string& verdict) {
@@ -635,8 +640,4 @@
   throttles_.clear();
 }
 
-void PasswordProtectionRequest::WebContentsDestroyed() {
-  Cancel(/*timed_out=*/false);
-}
-
 }  // namespace safe_browsing
diff --git a/components/safe_browsing/content/password_protection/password_protection_request.h b/components/safe_browsing/content/password_protection/password_protection_request.h
index 2501d85d..03dcaf7b 100644
--- a/components/safe_browsing/content/password_protection/password_protection_request.h
+++ b/components/safe_browsing/content/password_protection/password_protection_request.h
@@ -18,8 +18,8 @@
 #include "components/safe_browsing/content/common/safe_browsing.mojom.h"
 #include "components/safe_browsing/content/password_protection/password_protection_service.h"
 #include "components/safe_browsing/core/password_protection/metrics_util.h"
+#include "components/safe_browsing/core/password_protection/request_canceler.h"
 #include "components/safe_browsing/core/proto/csd.pb.h"
-#include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -70,7 +70,7 @@
 class PasswordProtectionRequest
     : public base::RefCountedThreadSafe<PasswordProtectionRequest,
                                         DeleteOnUIThread>,
-      public content::WebContentsObserver {
+      public CancelableRequest {
  public:
   PasswordProtectionRequest(
       content::WebContents* web_contents,
@@ -95,9 +95,8 @@
   // conditions.
   void Start();
 
-  // Cancels the current request. |timed_out| indicates if this cancellation is
-  // due to timeout. This function will call Finish() to destroy |this|.
-  void Cancel(bool timed_out);
+  // CancelableRequest implementation
+  void Cancel(bool timed_out) override;
 
   // Processes the received response.
   void OnURLLoaderComplete(std::unique_ptr<std::string> response_body);
@@ -151,9 +150,6 @@
   // Cancels navigation if there is modal warning showing, resumes it otherwise.
   void HandleDeferredNavigations();
 
-  // WebContentsObserver implementation
-  void WebContentsDestroyed() override;
-
  protected:
   friend class base::RefCountedThreadSafe<PasswordProtectionRequest>;
 
@@ -183,6 +179,9 @@
   void FillRequestProto(bool is_sampled_ping);
 
 #if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
+  // Extracts DOM features.
+  void GetDomFeatures();
+
   // Called when the DOM feature extraction is complete.
   void OnGetDomFeatures(mojom::PhishingDetectorResult result,
                         const std::string& verdict);
@@ -307,6 +306,9 @@
   bool dom_features_collection_complete_;
 #endif
 
+  // Cancels the request when it is no longer valid.
+  std::unique_ptr<RequestCanceler> request_canceler_;
+
   base::WeakPtrFactory<PasswordProtectionRequest> weakptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(PasswordProtectionRequest);
 };
diff --git a/components/safe_browsing/content/password_protection/request_canceler_content.cc b/components/safe_browsing/content/password_protection/request_canceler_content.cc
new file mode 100644
index 0000000..b4cbd9e
--- /dev/null
+++ b/components/safe_browsing/content/password_protection/request_canceler_content.cc
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/content/password_protection/request_canceler_content.h"
+
+namespace safe_browsing {
+
+std::unique_ptr<RequestCanceler> RequestCanceler::CreateRequestCanceler(
+    base::WeakPtr<CancelableRequest> request,
+    content::WebContents* web_contents) {
+  return std::make_unique<RequestCancelerContent>(request, web_contents);
+}
+
+RequestCancelerContent::RequestCancelerContent(
+    base::WeakPtr<CancelableRequest> request,
+    content::WebContents* web_contents)
+    : RequestCanceler(request), content::WebContentsObserver(web_contents) {}
+
+void RequestCancelerContent::WebContentsDestroyed() {
+  request_->Cancel(/*timed_out=*/false);
+}
+
+}  // namespace safe_browsing
diff --git a/components/safe_browsing/content/password_protection/request_canceler_content.h b/components/safe_browsing/content/password_protection/request_canceler_content.h
new file mode 100644
index 0000000..084b4c7
--- /dev/null
+++ b/components/safe_browsing/content/password_protection/request_canceler_content.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CONTENT_PASSWORD_PROTECTION_REQUEST_CANCELER_CONTENT_H_
+#define COMPONENTS_SAFE_BROWSING_CONTENT_PASSWORD_PROTECTION_REQUEST_CANCELER_CONTENT_H_
+
+#include "components/safe_browsing/core/password_protection/request_canceler.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace safe_browsing {
+
+class RequestCancelerContent : public RequestCanceler,
+                               public content::WebContentsObserver {
+ public:
+  RequestCancelerContent(base::WeakPtr<CancelableRequest> request,
+                         content::WebContents* web_contents);
+  ~RequestCancelerContent() override = default;
+
+ private:
+  // WebContentsObserver implementation
+  void WebContentsDestroyed() override;
+};
+
+}  // namespace safe_browsing
+
+#endif  // COMPONENTS_SAFE_BROWSING_CONTENT_PASSWORD_PROTECTION_REQUEST_CANCELER_CONTENT_H_
diff --git a/components/safe_browsing/content/triggers/ad_popup_trigger.cc b/components/safe_browsing/content/triggers/ad_popup_trigger.cc
index 3206c87..3080f0b 100644
--- a/components/safe_browsing/content/triggers/ad_popup_trigger.cc
+++ b/components/safe_browsing/content/triggers/ad_popup_trigger.cc
@@ -71,22 +71,6 @@
 
 AdPopupTrigger::~AdPopupTrigger() {}
 
-// static
-void AdPopupTrigger::CreateForWebContents(
-    content::WebContents* web_contents,
-    TriggerManager* trigger_manager,
-    PrefService* prefs,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    history::HistoryService* history_service) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new AdPopupTrigger(
-                                  web_contents, trigger_manager, prefs,
-                                  url_loader_factory, history_service)));
-  }
-}
-
 void AdPopupTrigger::CreateAdPopupReport() {
   SBErrorOptions error_options =
       TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents_);
diff --git a/components/safe_browsing/content/triggers/ad_popup_trigger.h b/components/safe_browsing/content/triggers/ad_popup_trigger.h
index a10a166..aed09b31 100644
--- a/components/safe_browsing/content/triggers/ad_popup_trigger.h
+++ b/components/safe_browsing/content/triggers/ad_popup_trigger.h
@@ -50,13 +50,6 @@
  public:
   ~AdPopupTrigger() override;
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      TriggerManager* trigger_manager,
-      PrefService* prefs,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      history::HistoryService* history_service);
-
   void PopupWasBlocked(content::RenderFrameHost* render_frame);
 
  private:
diff --git a/components/safe_browsing/content/triggers/ad_redirect_trigger.cc b/components/safe_browsing/content/triggers/ad_redirect_trigger.cc
index 842274e..7f49cd3 100644
--- a/components/safe_browsing/content/triggers/ad_redirect_trigger.cc
+++ b/components/safe_browsing/content/triggers/ad_redirect_trigger.cc
@@ -70,22 +70,6 @@
 
 AdRedirectTrigger::~AdRedirectTrigger() {}
 
-// static
-void AdRedirectTrigger::CreateForWebContents(
-    content::WebContents* web_contents,
-    TriggerManager* trigger_manager,
-    PrefService* prefs,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    history::HistoryService* history_service) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new AdRedirectTrigger(
-                                  web_contents, trigger_manager, prefs,
-                                  url_loader_factory, history_service)));
-  }
-}
-
 void AdRedirectTrigger::CreateAdRedirectReport() {
   SBErrorOptions error_options =
       TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents_);
diff --git a/components/safe_browsing/content/triggers/ad_redirect_trigger.h b/components/safe_browsing/content/triggers/ad_redirect_trigger.h
index 641c7fa..a4f9563 100644
--- a/components/safe_browsing/content/triggers/ad_redirect_trigger.h
+++ b/components/safe_browsing/content/triggers/ad_redirect_trigger.h
@@ -59,20 +59,6 @@
  public:
   ~AdRedirectTrigger() override;
 
-  // |web_contents| is the WebContent of the page that a redirect event took
-  // place on. |trigger_manager| ensures the trigger is only fired when
-  // appropriate and keeps track of how often the trigger is fired. |prefs|
-  // allows us to check that the user has opted in to Extended Reporting.
-  // |url_loader_factory| allows us to access mojom::URLLoaderFactory.
-  // |history_service| records page titles, visit times, and favicons, as well
-  // as information about downloads.
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      TriggerManager* trigger_manager,
-      PrefService* prefs,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      history::HistoryService* history_service);
-
   // This method is called on the browser thread when a frame tries to navigate
   // its top level frame from the |initiator_url| without ever having received a
   // user gesture. If the frame causing the redirect navigation is a Google Ad
@@ -83,6 +69,13 @@
   friend class AdRedirectTriggerBrowserTest;
   friend class content::WebContentsUserData<AdRedirectTrigger>;
 
+  // |web_contents| is the WebContent of the page that a redirect event took
+  // place on. |trigger_manager| ensures the trigger is only fired when
+  // appropriate and keeps track of how often the trigger is fired. |prefs|
+  // allows us to check that the user has opted in to Extended Reporting.
+  // |url_loader_factory| allows us to access mojom::URLLoaderFactory.
+  // |history_service| records page titles, visit times, and favicons, as well
+  // as information about downloads.
   AdRedirectTrigger(
       content::WebContents* web_contents,
       TriggerManager* trigger_manager,
diff --git a/components/safe_browsing/content/triggers/ad_sampler_trigger.cc b/components/safe_browsing/content/triggers/ad_sampler_trigger.cc
index 7cf7372..eb003d12 100644
--- a/components/safe_browsing/content/triggers/ad_sampler_trigger.cc
+++ b/components/safe_browsing/content/triggers/ad_sampler_trigger.cc
@@ -97,22 +97,6 @@
 
 AdSamplerTrigger::~AdSamplerTrigger() {}
 
-// static
-void AdSamplerTrigger::CreateForWebContents(
-    content::WebContents* web_contents,
-    TriggerManager* trigger_manager,
-    PrefService* prefs,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    history::HistoryService* history_service) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(UserDataKey(),
-                              base::WrapUnique(new AdSamplerTrigger(
-                                  web_contents, trigger_manager, prefs,
-                                  url_loader_factory, history_service)));
-  }
-}
-
 void AdSamplerTrigger::DidFinishLoad(
     content::RenderFrameHost* render_frame_host,
     const GURL& validated_url) {
diff --git a/components/safe_browsing/content/triggers/ad_sampler_trigger.h b/components/safe_browsing/content/triggers/ad_sampler_trigger.h
index 589bb1c..7223d17 100644
--- a/components/safe_browsing/content/triggers/ad_sampler_trigger.h
+++ b/components/safe_browsing/content/triggers/ad_sampler_trigger.h
@@ -61,13 +61,6 @@
  public:
   ~AdSamplerTrigger() override;
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      TriggerManager* trigger_manager,
-      PrefService* prefs,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      history::HistoryService* history_service);
-
   // content::WebContentsObserver implementation.
   void DidFinishLoad(content::RenderFrameHost* render_frame_host,
                      const GURL& validated_url) override;
diff --git a/components/safe_browsing/content/triggers/suspicious_site_trigger.cc b/components/safe_browsing/content/triggers/suspicious_site_trigger.cc
index f144ab0f..8c0a5e1 100644
--- a/components/safe_browsing/content/triggers/suspicious_site_trigger.cc
+++ b/components/safe_browsing/content/triggers/suspicious_site_trigger.cc
@@ -71,22 +71,6 @@
 
 SuspiciousSiteTrigger::~SuspiciousSiteTrigger() {}
 
-// static
-void SuspiciousSiteTrigger::CreateForWebContents(
-    content::WebContents* web_contents,
-    TriggerManager* trigger_manager,
-    PrefService* prefs,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    history::HistoryService* history_service,
-    bool monitor_mode) {
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(
-        UserDataKey(), base::WrapUnique(new SuspiciousSiteTrigger(
-                           web_contents, trigger_manager, prefs,
-                           url_loader_factory, history_service, monitor_mode)));
-  }
-}
-
 bool SuspiciousSiteTrigger::MaybeStartReport() {
   SBErrorOptions error_options =
       TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents());
diff --git a/components/safe_browsing/content/triggers/suspicious_site_trigger.h b/components/safe_browsing/content/triggers/suspicious_site_trigger.h
index 9d85f89a..9c3432b8 100644
--- a/components/safe_browsing/content/triggers/suspicious_site_trigger.h
+++ b/components/safe_browsing/content/triggers/suspicious_site_trigger.h
@@ -109,14 +109,6 @@
 
   ~SuspiciousSiteTrigger() override;
 
-  static void CreateForWebContents(
-      content::WebContents* web_contents,
-      TriggerManager* trigger_manager,
-      PrefService* prefs,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      history::HistoryService* history_service,
-      bool monitor_mode);
-
   // content::WebContentsObserver implementations.
   void DidStartLoading() override;
   void DidStopLoading() override;
diff --git a/components/safe_browsing/core/password_protection/BUILD.gn b/components/safe_browsing/core/password_protection/BUILD.gn
index e58fdba..0ebcb7bc 100644
--- a/components/safe_browsing/core/password_protection/BUILD.gn
+++ b/components/safe_browsing/core/password_protection/BUILD.gn
@@ -2,6 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+source_set("password_protection") {
+  sources = [
+    "request_canceler.cc",
+    "request_canceler.h",
+  ]
+
+  deps = [ "//base" ]
+}
+
 source_set("password_protection_metrics_util") {
   sources = [
     "metrics_util.cc",
diff --git a/components/safe_browsing/core/password_protection/request_canceler.cc b/components/safe_browsing/core/password_protection/request_canceler.cc
new file mode 100644
index 0000000..1096892b
--- /dev/null
+++ b/components/safe_browsing/core/password_protection/request_canceler.cc
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/core/password_protection/request_canceler.h"
+
+namespace safe_browsing {
+
+CancelableRequest::~CancelableRequest() = default;
+
+RequestCanceler::RequestCanceler(base::WeakPtr<CancelableRequest> request)
+    : request_(request) {}
+
+RequestCanceler::~RequestCanceler() = default;
+
+}  // namespace safe_browsing
\ No newline at end of file
diff --git a/components/safe_browsing/core/password_protection/request_canceler.h b/components/safe_browsing/core/password_protection/request_canceler.h
new file mode 100644
index 0000000..df903c9a
--- /dev/null
+++ b/components/safe_browsing/core/password_protection/request_canceler.h
@@ -0,0 +1,52 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CORE_PASSWORD_PROTECTION_REQUEST_CANCELER_H_
+#define COMPONENTS_SAFE_BROWSING_CORE_PASSWORD_PROTECTION_REQUEST_CANCELER_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace web {
+class WebState;
+}
+
+namespace safe_browsing {
+
+// An interface-only pure abstract base class for a request that can be
+// canceled.
+class CancelableRequest {
+ public:
+  virtual ~CancelableRequest() = 0;
+
+  // Cancels this request. |timed_out| indicates if this cancellation is
+  // due to timeout.
+  virtual void Cancel(bool timed_out) = 0;
+};
+
+// An object that cancels a request when it is no longer valid.
+class RequestCanceler {
+ public:
+  static std::unique_ptr<RequestCanceler> CreateRequestCanceler(
+      base::WeakPtr<CancelableRequest> request,
+      content::WebContents* web_contents);
+  static std::unique_ptr<RequestCanceler> CreateRequestCanceler(
+      base::WeakPtr<CancelableRequest> request,
+      web::WebState* web_state);
+
+  RequestCanceler(const RequestCanceler&) = delete;
+  RequestCanceler& operator=(const RequestCanceler&) = delete;
+  virtual ~RequestCanceler() = 0;
+
+ protected:
+  explicit RequestCanceler(base::WeakPtr<CancelableRequest> request);
+  base::WeakPtr<CancelableRequest> request_;
+};
+
+}  // namespace safe_browsing
+
+#endif  // COMPONENTS_SAFE_BROWSING_CORE_PASSWORD_PROTECTION_REQUEST_CANCELER_H_
diff --git a/components/safe_browsing/core/triggers/trigger_manager.cc b/components/safe_browsing/core/triggers/trigger_manager.cc
index d2b642a2..43594d3 100644
--- a/components/safe_browsing/core/triggers/trigger_manager.cc
+++ b/components/safe_browsing/core/triggers/trigger_manager.cc
@@ -241,17 +241,6 @@
 
 TriggerManagerWebContentsHelper::~TriggerManagerWebContentsHelper() {}
 
-void TriggerManagerWebContentsHelper::CreateForWebContents(
-    content::WebContents* web_contents,
-    TriggerManager* trigger_manager) {
-  DCHECK(web_contents);
-  if (!FromWebContents(web_contents)) {
-    web_contents->SetUserData(
-        UserDataKey(), base::WrapUnique(new TriggerManagerWebContentsHelper(
-                           web_contents, trigger_manager)));
-  }
-}
-
 void TriggerManagerWebContentsHelper::WebContentsDestroyed() {
   trigger_manager_->WebContentsDestroyed(web_contents());
 }
diff --git a/components/safe_browsing/core/triggers/trigger_manager.h b/components/safe_browsing/core/triggers/trigger_manager.h
index 145c814f..f7663cc9 100644
--- a/components/safe_browsing/core/triggers/trigger_manager.h
+++ b/components/safe_browsing/core/triggers/trigger_manager.h
@@ -202,11 +202,6 @@
  public:
   ~TriggerManagerWebContentsHelper() override;
 
-  // Creates a TriggerManagerWebContentsHelper and scopes its lifetime to the
-  // specified |web_contents|.
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   TriggerManager* trigger_manager);
-
   // WebContentsObserver implementation.
   void WebContentsDestroyed() override;
 
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc
index 8cb42f4..e84bac4 100644
--- a/components/search/ntp_features.cc
+++ b/components/search/ntp_features.cc
@@ -91,6 +91,9 @@
 const char kNtpRepeatableQueriesInsertPositionParam[] =
     "NtpRepeatableQueriesInsertPosition";
 
+const char kNtpStatefulTasksModuleDataParam[] =
+    "NtpStatefulTasksModuleDataParam";
+
 base::Time GetLocalHistoryRepeatableQueriesAgeThreshold() {
   const base::TimeDelta kLocalHistoryRepeatableQueriesAgeThreshold =
       base::TimeDelta::FromDays(180);  // Six months.
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h
index 7169943..d2f6e1e 100644
--- a/components/search/ntp_features.h
+++ b/components/search/ntp_features.h
@@ -56,6 +56,9 @@
   kEnd,        // At the end of MV tiles.
 };
 
+// Parameter determining the type of stateful data to request.
+extern const char kNtpStatefulTasksModuleDataParam[];
+
 // Returns the age threshold for local history repeatable queries.
 base::Time GetLocalHistoryRepeatableQueriesAgeThreshold();
 // Returns the number of seconds until the recency component of the frecency
diff --git a/components/search_provider_logos/DEPS b/components/search_provider_logos/DEPS
index 3f14730..6c8276f 100644
--- a/components/search_provider_logos/DEPS
+++ b/components/search_provider_logos/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/google/core",
   "+components/image_fetcher/core",
   "+components/keyed_service/core",
   "+components/search_engines",
diff --git a/components/search_provider_logos/google_logo_api.cc b/components/search_provider_logos/google_logo_api.cc
index f017e62..b397681c 100644
--- a/components/search_provider_logos/google_logo_api.cc
+++ b/components/search_provider_logos/google_logo_api.cc
@@ -21,6 +21,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
+#include "components/google/core/common/google_util.h"
 #include "components/search_provider_logos/switches.h"
 #include "url/third_party/mozilla/url_parse.h"
 #include "url/url_constants.h"
@@ -32,46 +33,6 @@
 const int kDefaultIframeWidthPx = 500;
 const int kDefaultIframeHeightPx = 200;
 
-// Appends the provided |value| to the "async" query param, according to the
-// format used by the Google doodle servers: "async=param:value,other:foo"
-// Derived from net::AppendOrReplaceQueryParameter, that can't be used because
-// it escapes ":" to "%3A", but the server requires the colon not to be escaped.
-// See: http://crbug.com/413845
-GURL AppendToAsyncQueryparam(const GURL& url, const std::string& value) {
-  const std::string param_name = "async";
-  bool replaced = false;
-  const std::string input = url.query();
-  url::Component cursor(0, input.size());
-  std::string output;
-  url::Component key_range, value_range;
-  while (url::ExtractQueryKeyValue(input.data(), &cursor, &key_range,
-                                   &value_range)) {
-    const base::StringPiece key(input.data() + key_range.begin, key_range.len);
-    std::string key_value_pair(input, key_range.begin,
-                               value_range.end() - key_range.begin);
-    if (!replaced && key == param_name) {
-      // Check |replaced| as only the first match should be replaced.
-      replaced = true;
-      key_value_pair += "," + value;
-    }
-    if (!output.empty()) {
-      output += "&";
-    }
-
-    output += key_value_pair;
-  }
-  if (!replaced) {
-    if (!output.empty()) {
-      output += "&";
-    }
-
-    output += (param_name + "=" + value);
-  }
-  GURL::Replacements replacements;
-  replacements.SetQueryStr(output);
-  return url.ReplaceComponents(replacements);
-}
-
 }  // namespace
 
 GURL GetGoogleDoodleURL(const GURL& google_base_url) {
@@ -98,18 +59,18 @@
     return logo_url;
   }
 
-  return AppendToAsyncQueryparam(logo_url, "es_dfp:" + fingerprint);
+  return google_util::AppendToAsyncQueryParam(logo_url, "es_dfp", fingerprint);
 }
 
 GURL AppendPreliminaryParamsToDoodleURL(bool gray_background,
                                         bool for_webui_ntp,
                                         const GURL& logo_url) {
-  std::string api_params = for_webui_ntp ? "ntp:2" : "ntp:1";
+  auto url = google_util::AppendToAsyncQueryParam(logo_url, "ntp",
+                                                  for_webui_ntp ? "2" : "1");
   if (gray_background) {
-    api_params += ",graybg:1";
+    url = google_util::AppendToAsyncQueryParam(url, "graybg", "1");
   }
-
-  return AppendToAsyncQueryparam(logo_url, api_params);
+  return url;
 }
 
 namespace {
diff --git a/components/sessions/content/session_tab_helper.cc b/components/sessions/content/session_tab_helper.cc
index 5350696..bf02947 100644
--- a/components/sessions/content/session_tab_helper.cc
+++ b/components/sessions/content/session_tab_helper.cc
@@ -28,15 +28,6 @@
 
 SessionTabHelper::~SessionTabHelper() = default;
 
-void SessionTabHelper::CreateForWebContents(content::WebContents* contents,
-                                            DelegateLookup lookup) {
-  DCHECK(contents);
-  if (!FromWebContents(contents)) {
-    contents->SetUserData(UserDataKey(), base::WrapUnique(new SessionTabHelper(
-                                             contents, std::move(lookup))));
-  }
-}
-
 void SessionTabHelper::SetWindowID(const SessionID& id) {
   window_id_ = id;
 
diff --git a/components/sessions/content/session_tab_helper.h b/components/sessions/content/session_tab_helper.h
index ddba15a..d101b0b 100644
--- a/components/sessions/content/session_tab_helper.h
+++ b/components/sessions/content/session_tab_helper.h
@@ -26,9 +26,6 @@
 
   ~SessionTabHelper() override;
 
-  static void CreateForWebContents(content::WebContents* contents,
-                                   DelegateLookup lookup);
-
   // Returns the identifier used by session restore for this tab.
   const SessionID& session_id() const { return session_id_; }
 
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index 397be1a..a3cac9b 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//components/signin/features.gni")
 
 if (is_android) {
@@ -65,6 +66,7 @@
   ]
   deps = [
     "//base:i18n",
+    "//build:chromeos_buildflags",
     "//components/google/core/common",
     "//components/metrics",
     "//components/os_crypt",
@@ -77,7 +79,7 @@
     "//third_party/icu",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "active_directory_account_reconcilor_delegate.cc",
       "active_directory_account_reconcilor_delegate.h",
@@ -116,6 +118,7 @@
     ":browser",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/content_settings/core/browser",
     "//components/prefs",
     "//components/prefs:test_support",
@@ -134,7 +137,7 @@
     "//url",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//chromeos/tpm:test_support" ]
     sources -= [
       "account_investigator_unittest.cc",
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index e949c1b6..a3fdb14a 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -16,6 +16,7 @@
 #include "base/time/time_to_iso8601.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_reconcilor.h"
@@ -669,7 +670,7 @@
   AddSectionEntry(basic_info, "Account Reconcilor blocked",
                   account_reconcilor->IsReconcileBlocked() ? "True" : "False");
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Time and status information of the possible sign in types.
   base::ListValue* detailed_info =
       AddSection(signin_info.get(), "Last Signin Details");
@@ -707,7 +708,7 @@
     AddSectionEntry(detailed_info, "Token Service Next Retry",
                     base::TimeToISO8601(next_retry_time), "");
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   signin_status->Set("signin_info", std::move(signin_info));
 
   // Token information for all services.
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 0886d81..83e91923 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
@@ -44,7 +45,7 @@
 #include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/tpm/stub_install_attributes.h"
 #include "components/signin/core/browser/active_directory_account_reconcilor_delegate.h"
 #endif
@@ -779,7 +780,7 @@
   }
 };
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(AccountReconcilorMirrorTest, IdentityManagerRegistration) {
   AccountReconcilor* reconcilor = GetMockReconcilor();
@@ -812,7 +813,7 @@
   ASSERT_TRUE(reconcilor->IsRegisteredWithIdentityManager());
 }
 
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(AccountReconcilorMirrorTest, ProfileAlreadyConnected) {
   ConnectProfileToAccount("user@gmail.com");
@@ -1749,7 +1750,7 @@
     AccountReconcilorTestMirrorMultilogin,
     ::testing::ValuesIn(GenerateTestCasesFromParams(kMirrorParams)));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class AccountReconcilorTestActiveDirectory : public AccountReconcilorTestTable {
  public:
   AccountReconcilorTestActiveDirectory() = default;
@@ -1869,7 +1870,7 @@
     ActiveDirectoryTable,
     AccountReconcilorTestActiveDirectory,
     ::testing::ValuesIn(GenerateTestCasesFromParams(kActiveDirectoryParams)));
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Tests that reconcile cannot start before the tokens are loaded, and is
 // automatically started when tokens are loaded.
@@ -2268,7 +2269,7 @@
   identity_test_env()->identity_manager()->RemoveObserver(&observer);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // This test does not run on ChromeOS because it clears the primary account,
 // which is not a flow that exists on ChromeOS.
 
@@ -2306,7 +2307,7 @@
   expected_counts["Signin.Reconciler.Duration.UpTo3mins.Failure"] = 1;
 }
 
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(AccountReconcilorMirrorTest, StartReconcileRemoveFromCookie) {
   AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 87f9ffd..6ea19764 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/google/core/common/google_util.h"
 #include "components/signin/core/browser/cookie_settings_util.h"
 #include "google_apis/gaia/gaia_auth_util.h"
@@ -196,7 +197,7 @@
 // Sessions and Active Directory logins. Guest Sessions have already been
 // filtered upstream and we want to enforce account consistency in Public
 // Sessions and Active Directory logins.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (!force_account_consistency && gaia_id.empty()) {
 #if defined(OS_ANDROID) || defined(OS_IOS)
     if (base::FeatureList::IsEnabled(kMobileIdentityConsistency) &&
@@ -208,7 +209,7 @@
 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
     return std::string();
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   if (!gaia_id.empty() &&
       IsUrlEligibleToIncludeGaiaId(url, is_header_request)) {
diff --git a/components/signin/core/browser/signin_error_controller_unittest.cc b/components/signin/core/browser/signin_error_controller_unittest.cc
index a8f0f7a2..4cf9bfc 100644
--- a/components/signin/core/browser/signin_error_controller_unittest.cc
+++ b/components/signin/core/browser/signin_error_controller_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/scoped_observation.h"
 #include "base/stl_util.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/signin/public/identity_manager/primary_account_mutator.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -138,7 +139,7 @@
 
 // This test exercises behavior on signin/signout, which is not relevant on
 // ChromeOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
   base::test::TaskEnvironment task_environment;
   signin::IdentityTestEnvironment identity_test_env;
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 362a30c..90526fe 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/prefs/pref_member.h"
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
@@ -153,7 +154,7 @@
   scoped_refptr<content_settings::CookieSettings> cookie_settings_;
 };
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Tests that Mirror request is returned on Chrome OS for Public Sessions (no
 // account id).
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdChromeOS) {
@@ -167,7 +168,7 @@
                            "mode=0:enable_account_consistency=true:"
                            "consistency_enabled_by_default=false");
 }
-#else  // !defined(OS_CHROMEOS)
+#else  // !BUILDFLAG(IS_CHROMEOS_ASH)
 #if defined(OS_ANDROID) || defined(OS_IOS)
 // Tests that eligible_for_consistency request is returned on mobile (Android,
 // iOS) when reaching to Gaia origin and there's no primary account. Only
diff --git a/components/signin/features.gni b/components/signin/features.gni
index f4636ab..dea221e 100644
--- a/components/signin/features.gni
+++ b/components/signin/features.gni
@@ -2,8 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
+
 # Dice is supported on the platform (but not necessarily enabled).
-enable_dice_support = (is_linux && !is_chromeos) || is_mac || is_win
+enable_dice_support = is_linux || is_chromeos_lacros || is_mac || is_win
 
 # Mirror is enabled and other account consistency mechanisms are not available.
 enable_mirror = is_android || is_ios
diff --git a/components/signin/internal/identity_manager/BUILD.gn b/components/signin/internal/identity_manager/BUILD.gn
index 8934830..a061d5bd 100644
--- a/components/signin/internal/identity_manager/BUILD.gn
+++ b/components/signin/internal/identity_manager/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//components/signin/features.gni")
 
 # This target forms the core of the IdentityManager implementation
@@ -56,6 +57,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//components/image_fetcher/core",
     "//components/prefs",
     "//components/signin/public/webdata",
@@ -84,7 +86,7 @@
     ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "profile_oauth2_token_service_delegate_chromeos.cc",
       "profile_oauth2_token_service_delegate_chromeos.h",
@@ -149,6 +151,7 @@
     ":test_support",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/image_fetcher/core",
     "//components/image_fetcher/core:test_support",
     "//components/os_crypt:test_support",
@@ -174,7 +177,7 @@
     sources += [ "profile_oauth2_token_service_delegate_android_unittest.cc" ]
   }
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [ "profile_oauth2_token_service_delegate_chromeos_unittest.cc" ]
 
     deps += [ "//chromeos/components/account_manager" ]
@@ -206,7 +209,7 @@
     "fake_profile_oauth2_token_service_delegate.h",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     sources += [
       "test_profile_oauth2_token_service_delegate_chromeos.cc",
       "test_profile_oauth2_token_service_delegate_chromeos.h",
diff --git a/components/signin/internal/identity_manager/account_tracker_service.cc b/components/signin/internal/identity_manager/account_tracker_service.cc
index 3083c0e..07aa4aa 100644
--- a/components/signin/internal/identity_manager/account_tracker_service.cc
+++ b/components/signin/internal/identity_manager/account_tracker_service.cc
@@ -23,6 +23,7 @@
 #include "base/threading/scoped_blocking_call.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/signin/internal/identity_manager/account_info_util.h"
diff --git a/components/signin/internal/identity_manager/account_tracker_service_unittest.cc b/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
index d12619a2..cad98d3 100644
--- a/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
+++ b/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/fake_image_decoder.h"
 #include "components/image_fetcher/core/image_data_fetcher.h"
 #include "components/prefs/pref_service.h"
@@ -55,7 +56,7 @@
 const AccountKey kAccountKeyFooBar = {"foobar"};
 const AccountKey kAccountKeyFooDotBar = {"foo.bar"};
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_IOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_IOS)
 const AccountKey kAccountKeyAdvancedProtection = {"advanced_protection"};
 #endif
 
@@ -760,7 +761,7 @@
                                        true);
 #endif
 
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID) && !defined(OS_IOS)
   account_tracker()->SetIsAdvancedProtectionAccount(
       AccountKeyToAccountId(kAccountKeyBeta), true);
 #endif
@@ -773,7 +774,7 @@
   ASSERT_EQ(1u, infos.size());
   CheckAccountDetails(kAccountKeyBeta, infos[0]);
   EXPECT_TRUE(infos[0].is_child_account);
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID) && !defined(OS_IOS)
   EXPECT_TRUE(infos[0].is_under_advanced_protection);
 #else
   EXPECT_FALSE(infos[0].is_under_advanced_protection);
@@ -1364,7 +1365,7 @@
   }));
 }
 
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_IOS)
+#if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_IOS)
 TEST_F(AccountTrackerServiceTest, AdvancedProtectionAccountBasic) {
   SimulateTokenAvailable(kAccountKeyAdvancedProtection);
   IssueAccessToken(kAccountKeyAdvancedProtection);
diff --git a/components/signin/internal/identity_manager/accounts_mutator_impl.cc b/components/signin/internal/identity_manager/accounts_mutator_impl.cc
index 271fe09e..5c683a8 100644
--- a/components/signin/internal/identity_manager/accounts_mutator_impl.cc
+++ b/components/signin/internal/identity_manager/accounts_mutator_impl.cc
@@ -5,6 +5,7 @@
 #include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
 
 #include "base/optional.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/primary_account_manager.h"
@@ -42,7 +43,7 @@
     const std::string& refresh_token,
     bool is_under_advanced_protection,
     signin_metrics::SourceForRefreshTokenOperation source) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   NOTREACHED();
 #endif
   CoreAccountId account_id =
@@ -78,7 +79,7 @@
 void AccountsMutatorImpl::RemoveAccount(
     const CoreAccountId& account_id,
     signin_metrics::SourceForRefreshTokenOperation source) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   NOTREACHED();
 #endif
   token_service_->RevokeCredentials(account_id, source);
@@ -86,7 +87,7 @@
 
 void AccountsMutatorImpl::RemoveAllAccounts(
     signin_metrics::SourceForRefreshTokenOperation source) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   NOTREACHED();
 #endif
   token_service_->RevokeAllCredentials(source);
@@ -94,7 +95,7 @@
 
 void AccountsMutatorImpl::InvalidateRefreshTokenForPrimaryAccount(
     signin_metrics::SourceForRefreshTokenOperation source) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   NOTREACHED();
 #endif
   DCHECK(primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync));
diff --git a/components/signin/internal/identity_manager/primary_account_manager.cc b/components/signin/internal/identity_manager/primary_account_manager.cc
index ef0bad6d..657c94a 100644
--- a/components/signin/internal/identity_manager/primary_account_manager.cc
+++ b/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
@@ -33,7 +34,7 @@
       token_service_(token_service),
       account_tracker_service_(account_tracker_service),
       initialized_(false),
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
       account_consistency_(account_consistency),
 #endif
       policy_manager_(std::move(policy_manager)) {
@@ -271,7 +272,7 @@
   observers_.RemoveObserver(observer);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void PrimaryAccountManager::SignOut(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric) {
@@ -295,9 +296,9 @@
   StartSignOut(signout_source_metric, signout_delete_metric,
                RemoveAccountsOption::kKeepAllAccounts);
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void PrimaryAccountManager::RevokeSyncConsent() {
   DCHECK(HasPrimaryAccount(signin::ConsentLevel::kSync));
   // TODO(https://crbug.com/1046746): Don't record metrics here.
@@ -306,7 +307,7 @@
                RemoveAccountsOption::kKeepAllAccounts,
                /*assert_signout_allowed=*/true);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void PrimaryAccountManager::StartSignOut(
     signin_metrics::ProfileSignout signout_source_metric,
diff --git a/components/signin/internal/identity_manager/primary_account_manager.h b/components/signin/internal/identity_manager/primary_account_manager.h
index 8bb524c..baaac24 100644
--- a/components/signin/internal/identity_manager/primary_account_manager.h
+++ b/components/signin/internal/identity_manager/primary_account_manager.h
@@ -25,6 +25,7 @@
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/optional.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_client.h"
@@ -117,7 +118,7 @@
 
   // Signout API surfaces (not supported on ChromeOS, where signout is not
   // permitted).
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Signs a user out, removing the preference, erasing all keys
   // associated with the authenticated user, and canceling all auth in progress.
   // On mobile and on desktop pre-DICE, this also removes all accounts from
@@ -141,14 +142,14 @@
   void SignOutAndKeepAllAccounts(
       signin_metrics::ProfileSignout signout_source_metric,
       signin_metrics::SignoutDelete signout_delete_metric);
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Revokes sync consent from the primary account. The primary account must
   // have sync consent. After the call a primary account will remain but it will
   // not have sync consent.
   void RevokeSyncConsent();
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Adds and removes observers.
   void AddObserver(Observer* observer);
@@ -215,7 +216,7 @@
   // this field.
   CoreAccountInfo primary_account_info_;
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   signin::AccountConsistencyMethod account_consistency_;
 #endif
 
diff --git a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
index c2af6ef..c16d8f4 100644
--- a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
+++ b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/fake_image_decoder.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -30,7 +31,7 @@
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
 #endif
 
@@ -89,7 +90,7 @@
     // production usage: null on ChromeOS, a PrimaryAccountPolicyManagerImpl on
     // other platforms.
     std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     policy_manager =
         std::make_unique<PrimaryAccountPolicyManagerImpl>(&test_signin_client_);
     policy_manager_ =
@@ -137,7 +138,7 @@
   ProfileOAuth2TokenService token_service_;
   AccountTrackerService account_tracker_;
   AccountFetcherService account_fetcher_;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   PrimaryAccountPolicyManagerImpl* policy_manager_;
 #endif
   std::unique_ptr<PrimaryAccountManager> manager_;
@@ -148,7 +149,7 @@
   int num_unconsented_account_changed_;
 };
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PrimaryAccountManagerTest, SignOut) {
   CreatePrimaryAccountManager();
   CoreAccountId main_account_id =
@@ -347,7 +348,7 @@
   EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PrimaryAccountManagerTest, SigninNotAllowed) {
   std::string user("user@google.com");
   CoreAccountId account_id = AddToAccountTracker("gaia_id", user);
@@ -512,7 +513,7 @@
   EXPECT_EQ(CoreAccountInfo(), manager_->GetAuthenticatedAccountInfo());
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PrimaryAccountManagerTest, RevokeSyncConsent) {
   CreatePrimaryAccountManager();
   CoreAccountId account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
@@ -525,4 +526,4 @@
   EXPECT_EQ(account_id,
             manager_->GetUnconsentedPrimaryAccountInfo().account_id);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
index e7d76e54..733f5316 100644
--- a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
+++ b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/check.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/primary_account_manager.h"
@@ -34,7 +35,7 @@
     const CoreAccountId& account_id) {
   AccountInfo account_info = account_tracker_->GetAccountInfo(account_id);
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (!pref_service_->GetBoolean(prefs::kSigninAllowed))
     return false;
 
@@ -53,7 +54,7 @@
 
 void PrimaryAccountMutatorImpl::SetUnconsentedPrimaryAccount(
     const CoreAccountId& account_id) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS the UPA can only be set once and never removed or changed.
   DCHECK(!account_id.empty());
   DCHECK(
@@ -68,13 +69,13 @@
   primary_account_manager_->SetUnconsentedPrimaryAccountInfo(account_info);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 void PrimaryAccountMutatorImpl::RevokeSyncConsent() {
   primary_account_manager_->RevokeSyncConsent();
 }
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 bool PrimaryAccountMutatorImpl::ClearPrimaryAccount(
     ClearAccountsAction action,
     signin_metrics::ProfileSignout source_metric,
diff --git a/components/signin/internal/identity_manager/primary_account_mutator_impl.h b/components/signin/internal/identity_manager/primary_account_mutator_impl.h
index 5e1d629..65313c1 100644
--- a/components/signin/internal/identity_manager/primary_account_mutator_impl.h
+++ b/components/signin/internal/identity_manager/primary_account_mutator_impl.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/identity_manager/primary_account_mutator.h"
 
 class AccountTrackerService;
@@ -27,10 +28,10 @@
   // PrimaryAccountMutator implementation.
   bool SetPrimaryAccount(const CoreAccountId& account_id) override;
   void SetUnconsentedPrimaryAccount(const CoreAccountId& account_id) override;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   void RevokeSyncConsent() override;
 #endif
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   bool ClearPrimaryAccount(
       ClearAccountsAction action,
       signin_metrics::ProfileSignout source_metric,
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
index a807003..804adebb 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -8,6 +8,7 @@
 #include "base/check_op.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
 #include "components/signin/public/base/device_id_helper.h"
@@ -447,7 +448,7 @@
 
 void ProfileOAuth2TokenService::RecreateDeviceIdIfNeeded() {
 // On ChromeOS the device ID is not managed by the token service.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (AreAllCredentialsLoaded() && HasLoadCredentialsFinishedWithNoErrors() &&
       GetAccounts().empty()) {
     signin::RecreateSigninScopedDeviceId(user_prefs_);
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
index f5dc498d..d2c890023 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "build/buildflag.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
 #include "components/signin/public/base/account_consistency_method.h"
@@ -23,11 +24,11 @@
 #include "components/signin/public/webdata/token_web_data.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/account_manager/account_manager.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
 #include "components/user_manager/user_manager.h"
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if defined(OS_IOS)
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
@@ -58,7 +59,7 @@
       signin_client, std::move(device_accounts_provider),
       account_tracker_service);
 }
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
 std::unique_ptr<signin::ProfileOAuth2TokenServiceDelegateChromeOS>
 CreateCrOsOAuthDelegate(
     AccountTrackerService* account_tracker_service,
@@ -106,7 +107,7 @@
     AccountTrackerService* account_tracker_service,
     signin::AccountConsistencyMethod account_consistency,
     SigninClient* signin_client,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager* account_manager,
     bool is_regular_profile,
 #endif
@@ -128,7 +129,7 @@
   return CreateIOSOAuthDelegate(signin_client,
                                 std::move(device_accounts_provider),
                                 account_tracker_service);
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return CreateCrOsOAuthDelegate(account_tracker_service,
                                  network_connection_tracker, account_manager,
                                  is_regular_profile);
@@ -155,7 +156,7 @@
     AccountTrackerService* account_tracker_service,
     network::NetworkConnectionTracker* network_connection_tracker,
     signin::AccountConsistencyMethod account_consistency,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager* account_manager,
     bool is_regular_profile,
 #endif
@@ -172,7 +173,7 @@
 #endif
     SigninClient* signin_client) {
 // On ChromeOS the device ID is not managed by the token service.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Ensure the device ID is not empty. This is important for Dice, because the
   // device ID is needed on the network thread, but can only be generated on the
   // main thread.
@@ -184,7 +185,7 @@
       pref_service,
       CreateOAuth2TokenServiceDelegate(
           account_tracker_service, account_consistency, signin_client,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
           account_manager, is_regular_profile,
 #endif
 #if !defined(OS_ANDROID)
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
index c39bf3524..5c6d123 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 #if !defined(OS_ANDROID)
 #include "base/memory/scoped_refptr.h"
@@ -38,7 +39,7 @@
 class TokenWebData;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 namespace chromeos {
 class AccountManager;
 }
@@ -49,7 +50,7 @@
     AccountTrackerService* account_tracker_service,
     network::NetworkConnectionTracker* network_connection_tracker,
     signin::AccountConsistencyMethod account_consistency,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager* account_manager,
     bool is_regular_profile,
 #endif
diff --git a/components/signin/public/base/BUILD.gn b/components/signin/public/base/BUILD.gn
index 80f8a72..ad1c498 100644
--- a/components/signin/public/base/BUILD.gn
+++ b/components/signin/public/base/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//components/signin/features.gni")
 
 if (is_android) {
@@ -39,6 +40,7 @@
     "signin_switches.h",
   ]
   deps = [
+    "//build:chromeos_buildflags",
     "//components/prefs",
     "//third_party/icu:icui18n",
     "//third_party/re2",
@@ -51,7 +53,7 @@
     "//url",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//components/user_manager" ]
   }
 }
@@ -97,6 +99,7 @@
     ":base",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/prefs:test_support",
     "//components/sync_preferences:test_support",
     "//testing/gtest",
diff --git a/components/signin/public/base/device_id_helper.cc b/components/signin/public/base/device_id_helper.cc
index e23896e8..e3c5185 100644
--- a/components/signin/public/base/device_id_helper.cc
+++ b/components/signin/public/base/device_id_helper.cc
@@ -7,13 +7,14 @@
 #include "base/check.h"
 #include "base/command_line.h"
 #include "base/guid.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/signin_pref_names.h"
 #include "components/signin/public/base/signin_switches.h"
 
 namespace signin {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 std::string GetSigninScopedDeviceId(PrefService* prefs) {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/components/signin/public/base/device_id_helper.h b/components/signin/public/base/device_id_helper.h
index 6bda97cd..c3cb1ae0 100644
--- a/components/signin/public/base/device_id_helper.h
+++ b/components/signin/public/base/device_id_helper.h
@@ -8,12 +8,13 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 class PrefService;
 
 namespace signin {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Returns device id that is scoped to single signin. This device id will be
 // regenerated if user signs out and signs back in.
diff --git a/components/signin/public/base/device_id_helper_unittest.cc b/components/signin/public/base/device_id_helper_unittest.cc
index 1a0e3003..e7205d1 100644
--- a/components/signin/public/base/device_id_helper_unittest.cc
+++ b/components/signin/public/base/device_id_helper_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/signin_pref_names.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -14,7 +15,7 @@
 namespace signin {
 namespace {
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST(DeviceIdHelper, GenerateSigninScopedDeviceId) {
   EXPECT_FALSE(GenerateSigninScopedDeviceId().empty());
diff --git a/components/signin/public/base/signin_pref_names.cc b/components/signin/public/base/signin_pref_names.cc
index d170c09d..4b79d6de 100644
--- a/components/signin/public/base/signin_pref_names.cc
+++ b/components/signin/public/base/signin_pref_names.cc
@@ -4,9 +4,11 @@
 
 #include "components/signin/public/base/signin_pref_names.h"
 
+#include "build/chromeos_buildflags.h"
+
 namespace prefs {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // A boolean pref - should unauthenticated user should be logged out
 // automatically. Default value is false.
 const char kForceLogoutUnauthenticatedUserEnabled[] =
diff --git a/components/signin/public/base/signin_pref_names.h b/components/signin/public/base/signin_pref_names.h
index c8610c5..849a94e 100644
--- a/components/signin/public/base/signin_pref_names.h
+++ b/components/signin/public/base/signin_pref_names.h
@@ -5,9 +5,11 @@
 #ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_PREF_NAMES_H_
 #define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_PREF_NAMES_H_
 
+#include "build/chromeos_buildflags.h"
+
 namespace prefs {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 extern const char kForceLogoutUnauthenticatedUserEnabled[];
 #endif
 extern const char kAccountIdMigrationState[];
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc
index a421aa7..9a4612c 100644
--- a/components/signin/public/base/signin_switches.cc
+++ b/components/signin/public/base/signin_switches.cc
@@ -4,6 +4,8 @@
 
 #include "components/signin/public/base/signin_switches.h"
 
+#include "build/chromeos_buildflags.h"
+
 namespace switches {
 
 // Clears the token service before using it. This allows simulating the
@@ -13,7 +15,7 @@
 // Disables sending signin scoped device id to LSO with refresh token request.
 const char kDisableSigninScopedDeviceId[] = "disable-signin-scoped-device-id";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const base::Feature kAccountIdMigration{"AccountIdMigration",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
diff --git a/components/signin/public/base/signin_switches.h b/components/signin/public/base/signin_switches.h
index e1241a1..fb3de39c 100644
--- a/components/signin/public/base/signin_switches.h
+++ b/components/signin/public/base/signin_switches.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
 
 #include "base/feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/signin_buildflags.h"
 
 namespace switches {
@@ -19,7 +20,7 @@
 extern const char kClearTokenService[];
 extern const char kDisableSigninScopedDeviceId[];
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 extern const base::Feature kAccountIdMigration;
 #endif
 
diff --git a/components/signin/public/identity_manager/BUILD.gn b/components/signin/public/identity_manager/BUILD.gn
index 6aaf413..66149ee 100644
--- a/components/signin/public/identity_manager/BUILD.gn
+++ b/components/signin/public/identity_manager/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
+
 if (is_android) {
   import("//build/config/android/rules.gni")
 }
@@ -51,6 +53,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//components/image_fetcher/core",
     "//components/prefs",
     "//components/signin/internal/identity_manager",
@@ -58,7 +61,7 @@
     "//services/network/public/cpp",
   ]
 
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//components/user_manager" ]
   }
 
@@ -108,6 +111,7 @@
     ":test_support",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/image_fetcher/core:test_support",
     "//components/prefs",
     "//components/prefs:test_support",
@@ -148,6 +152,7 @@
   ]
 
   deps = [
+    "//build:chromeos_buildflags",
     "//components/image_fetcher/core:test_support",
     "//components/signin/internal/identity_manager",
     "//components/signin/internal/identity_manager:test_support",
diff --git a/components/signin/public/identity_manager/accounts_mutator_unittest.cc b/components/signin/public/identity_manager/accounts_mutator_unittest.cc
index 521dee2a..4f993a8 100644
--- a/components/signin/public/identity_manager/accounts_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/accounts_mutator_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/optional.h"
 #include "base/test/gtest_util.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/device_id_helper.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -21,7 +22,7 @@
 namespace {
 
 const char kTestEmail[] = "test_user@test.com";
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 const char kTestGaiaId[] = "gaia-id-test_user-test.com";
 const char kTestGaiaId2[] = "gaia-id-test_user-2-test.com";
 const char kTestEmail2[] = "test_user@test-2.com";
@@ -212,7 +213,7 @@
   EXPECT_FALSE(reset_account_info.is_under_advanced_protection);
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Test that a new account gets added to the AccountTrackerService when calling
 // AddOrUpdateAccount() and that a new refresh token becomes available for the
 // passed account_id when adding an account for the first time.
@@ -617,7 +618,7 @@
   EXPECT_EQ("Settings::Signout",
             identity_manager_diagnostics_observer()->token_remover_source());
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 TEST_F(AccountsMutatorTest, MoveAccount) {
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc
index 7a293d0..37dc9de 100644
--- a/components/signin/public/identity_manager/identity_manager.cc
+++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/internal/identity_manager/account_fetcher_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
@@ -83,7 +84,7 @@
       token_service_->GetDelegate()->GetJavaObject());
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos_account_manager_ = parameters.chromeos_account_manager;
 #endif
 }
@@ -455,7 +456,7 @@
   return gaia_cookie_manager_service_.get();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 chromeos::AccountManager* IdentityManager::GetChromeOSAccountManager() const {
   return chromeos_account_manager_;
 }
diff --git a/components/signin/public/identity_manager/identity_manager.h b/components/signin/public/identity_manager/identity_manager.h
index d2e68f4e..eac95bf 100644
--- a/components/signin/public/identity_manager/identity_manager.h
+++ b/components/signin/public/identity_manager/identity_manager.h
@@ -12,6 +12,7 @@
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/internal/identity_manager/primary_account_manager.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
@@ -28,7 +29,7 @@
 #include "base/android/jni_android.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 namespace chromeos {
 class AccountManager;
 }  // namespace chromeos
@@ -397,7 +398,7 @@
     std::unique_ptr<AccountsMutator> accounts_mutator;
     std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer;
     std::unique_ptr<DiagnosticsProvider> diagnostics_provider;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager* chromeos_account_manager = nullptr;
 #endif
 
@@ -616,7 +617,7 @@
   AccountTrackerService* GetAccountTrackerService() const;
   AccountFetcherService* GetAccountFetcherService() const;
   GaiaCookieManagerService* GetGaiaCookieManagerService() const;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManager* GetChromeOSAccountManager() const;
 #endif
 
@@ -700,7 +701,7 @@
   base::android::ScopedJavaGlobalRef<jobject> java_identity_manager_;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManager* chromeos_account_manager_ = nullptr;
 #endif
 
diff --git a/components/signin/public/identity_manager/identity_manager_builder.cc b/components/signin/public/identity_manager/identity_manager_builder.cc
index 3f24bda..aa93a933 100644
--- a/components/signin/public/identity_manager/identity_manager_builder.cc
+++ b/components/signin/public/identity_manager/identity_manager_builder.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/image_decoder.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/internal/identity_manager/account_fetcher_service.h"
@@ -40,7 +41,7 @@
 #include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/signin/internal/identity_manager/primary_account_policy_manager_impl.h"
 #endif
 
@@ -64,7 +65,7 @@
     PrefService* local_state) {
   std::unique_ptr<PrimaryAccountManager> primary_account_manager;
   std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   policy_manager = std::make_unique<PrimaryAccountPolicyManagerImpl>(client);
 #endif
   primary_account_manager = std::make_unique<PrimaryAccountManager>(
@@ -114,7 +115,7 @@
       BuildProfileOAuth2TokenService(
           params->pref_service, account_tracker_service.get(),
           params->network_connection_tracker, params->account_consistency,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
           params->account_manager, params->is_regular_profile,
 #endif
 #if !defined(OS_ANDROID)
@@ -171,7 +172,7 @@
       std::move(gaia_cookie_manager_service);
   init_params.primary_account_manager = std::move(primary_account_manager);
   init_params.token_service = std::move(token_service);
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   init_params.chromeos_account_manager = params->account_manager;
 #endif
 
diff --git a/components/signin/public/identity_manager/identity_manager_builder.h b/components/signin/public/identity_manager/identity_manager_builder.h
index b2695b8..072dbb7 100644
--- a/components/signin/public/identity_manager/identity_manager_builder.h
+++ b/components/signin/public/identity_manager/identity_manager_builder.h
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 
 #if !defined(OS_ANDROID)
@@ -40,7 +41,7 @@
 class NetworkConnectionTracker;
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 namespace chromeos {
 class AccountManager;
 }
@@ -68,7 +69,7 @@
   scoped_refptr<TokenWebData> token_web_data;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManager* account_manager;
   bool is_regular_profile;
 #endif
diff --git a/components/signin/public/identity_manager/identity_manager_builder_unittest.cc b/components/signin/public/identity_manager/identity_manager_builder_unittest.cc
index 4ee471a..433a62c 100644
--- a/components/signin/public/identity_manager/identity_manager_builder_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_builder_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/fake_image_decoder.h"
 #include "components/signin/internal/identity_manager/account_fetcher_service.h"
 #include "components/signin/public/base/test_signin_client.h"
@@ -20,7 +21,7 @@
 #include "components/signin/public/identity_manager/identity_test_utils.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/account_manager/account_manager.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
 #endif
@@ -46,7 +47,7 @@
     return &pref_service_;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory* GetAccountManagerFactory() {
     return &account_manager_factory_;
   }
@@ -62,7 +63,7 @@
   sync_preferences::TestingPrefServiceSyncable pref_service_;
   network::TestURLLoaderFactory test_url_loader_factory_;
   TestSigninClient signin_client_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory account_manager_factory_;
 #endif
 };
@@ -93,7 +94,7 @@
       std::make_unique<FakeDeviceAccountsProvider>();
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManager* account_manager =
       GetAccountManagerFactory()->GetAccountManager(dest_path.value());
   account_manager->Initialize(
@@ -122,7 +123,7 @@
   EXPECT_EQ(init_params.device_accounts_synchronizer, nullptr);
   EXPECT_NE(init_params.accounts_mutator, nullptr);
 #endif
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_NE(init_params.chromeos_account_manager, nullptr);
 #endif
 
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc
index 5651763..926576bf 100644
--- a/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/fake_image_decoder.h"
 #include "components/signin/internal/identity_manager/account_fetcher_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
@@ -58,7 +59,7 @@
 #include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/account_manager/account_manager.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
 #include "components/account_manager_core/account.h"
@@ -83,7 +84,7 @@
 const char kTestLocale[] = "locale";
 const char kTestPictureUrl[] = "http://picture.example.com/picture.jpg";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kTestEmailWithPeriod[] = "m.e@gmail.com";
 #endif
 
@@ -306,7 +307,7 @@
                          std::string gaia_id,
                          std::string email,
                          std::string token) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     identity_manager()->GetChromeOSAccountManager()->UpsertAccount(
         ::account_manager::AccountKey{gaia_id,
                                       account_manager::AccountType::kGaia},
@@ -317,7 +318,7 @@
   }
 
   void RevokeCredentials(const CoreAccountId& account_id, std::string gaia_id) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     identity_manager()->GetChromeOSAccountManager()->RemoveAccount(
         ::account_manager::AccountKey{gaia_id,
                                       account_manager::AccountType::kGaia});
@@ -360,7 +361,7 @@
     account_tracker_service->Initialize(&pref_service_,
                                         temp_profile_dir_.GetPath());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager::RegisterPrefs(pref_service_.registry());
     chromeos::AccountManager* chromeos_account_manager =
         GetAccountManagerFactory()->GetAccountManager(
@@ -391,7 +392,7 @@
     DCHECK_EQ(account_consistency, AccountConsistencyMethod::kDisabled)
         << "AccountConsistency is not used by PrimaryAccountManager";
     std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     policy_manager =
         std::make_unique<PrimaryAccountPolicyManagerImpl>(&signin_client_);
 #endif
@@ -438,7 +439,7 @@
         token_service.get(), account_tracker_service.get(),
         primary_account_manager.get(), &pref_service_);
 #endif
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     init_params.chromeos_account_manager = chromeos_account_manager;
 #endif
 
@@ -489,7 +490,7 @@
     return &test_url_loader_factory_;
   }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory* GetAccountManagerFactory() {
     return &account_manager_factory_;
   }
@@ -498,7 +499,7 @@
  private:
   base::ScopedTempDir temp_profile_dir_;
   base::test::TaskEnvironment task_environment_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory account_manager_factory_;
 #endif
   sync_preferences::TestingPrefServiceSyncable pref_service_;
@@ -530,7 +531,7 @@
   EXPECT_NE(identity_manager()->GetAccountsMutator(), nullptr);
   EXPECT_EQ(identity_manager()->GetDeviceAccountsSynchronizer(), nullptr);
 #endif
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_NE(identity_manager()->GetChromeOSAccountManager(), nullptr);
 #endif
 }
@@ -551,7 +552,7 @@
 
 // Signin/signout tests aren't relevant and cannot build on ChromeOS, which
 // doesn't support signin/signout.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Test that the user signing in results in firing of the IdentityManager
 // observer callback and the IdentityManager's state being updated.
 TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSignin) {
@@ -650,7 +651,7 @@
   EXPECT_EQ(primary_account_id, identity_manager()->GetPrimaryAccountId(
                                     ConsentLevel::kNotRequired));
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(IdentityManagerTest, HasPrimaryAccount) {
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
@@ -664,7 +665,7 @@
   EXPECT_TRUE(
       identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Signing out should cause IdentityManager to recognize that there is no
   // longer a primary account.
   ClearPrimaryAccount(identity_manager(), ClearPrimaryAccountPolicy::DEFAULT);
@@ -1473,7 +1474,7 @@
   EXPECT_TRUE(mutator);
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // On ChromeOS, AccountTrackerService first receives the normalized email
 // address from GAIA and then later has it updated with the user's
 // originally-specified version of their email address (at the time of that
@@ -1576,7 +1577,7 @@
       identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(
     IdentityManagerTest,
     CallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidTokenWhenNoPrimaryAccount) {
diff --git a/components/signin/public/identity_manager/identity_test_environment.cc b/components/signin/public/identity_manager/identity_test_environment.cc
index 6f80d86d..d56cbc2 100644
--- a/components/signin/public/identity_manager/identity_test_environment.cc
+++ b/components/signin/public/identity_manager/identity_test_environment.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/image_fetcher/core/fake_image_decoder.h"
 #include "components/signin/internal/identity_manager/account_fetcher_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
@@ -35,7 +36,7 @@
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
 #include "services/network/test/test_url_loader_factory.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/account_manager/account_manager.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
 #include "components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h"
@@ -60,13 +61,13 @@
   ~IdentityManagerDependenciesOwner();
 
   sync_preferences::TestingPrefServiceSyncable* pref_service();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManagerFactory* account_manager_factory();
 #endif
   TestSigninClient* signin_client();
 
  private:
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<chromeos::AccountManagerFactory> account_manager_factory_;
 #endif
   // Depending on whether a |pref_service| instance is passed in
@@ -84,7 +85,7 @@
     sync_preferences::TestingPrefServiceSyncable* pref_service_param,
     TestSigninClient* signin_client_param)
     :
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       account_manager_factory_(
           std::make_unique<chromeos::AccountManagerFactory>()),
 #endif
@@ -111,7 +112,7 @@
   return raw_pref_service_ ? raw_pref_service_ : owned_pref_service_.get();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 chromeos::AccountManagerFactory*
 IdentityManagerDependenciesOwner::account_manager_factory() {
   DCHECK(account_manager_factory_);
@@ -181,7 +182,7 @@
 
   IdentityManager::RegisterProfilePrefs(test_pref_service->registry());
   IdentityManager::RegisterLocalStatePrefs(test_pref_service->registry());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   chromeos::AccountManager::RegisterPrefs(test_pref_service->registry());
 
   owned_identity_manager_ = BuildIdentityManagerForTests(
@@ -191,12 +192,12 @@
   owned_identity_manager_ =
       BuildIdentityManagerForTests(test_signin_client, test_pref_service,
                                    base::FilePath(), account_consistency);
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   Initialize();
 }
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // static
 std::unique_ptr<IdentityManager>
 IdentityTestEnvironment::BuildIdentityManagerForTests(
@@ -258,7 +259,7 @@
       std::move(token_service), signin_client, pref_service, user_data_dir,
       account_consistency);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 IdentityTestEnvironment::PendingRequest::PendingRequest(
     CoreAccountId account_id,
@@ -291,7 +292,7 @@
       std::make_unique<image_fetcher::FakeImageDecoder>());
 
   std::unique_ptr<PrimaryAccountPolicyManager> policy_manager;
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   policy_manager =
       std::make_unique<PrimaryAccountPolicyManagerImpl>(signin_client);
 #endif
@@ -389,7 +390,7 @@
 AccountInfo IdentityTestEnvironment::MakeUnconsentedPrimaryAccountAvailable(
     const std::string& email) {
   DCHECK(!identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Chrome OS sets the unconsented primary account during login and does not
   // allow signout.
   AccountInfo account_info = MakeAccountAvailable(email);
diff --git a/components/signin/public/identity_manager/identity_test_environment.h b/components/signin/public/identity_manager/identity_test_environment.h
index 2f4b6ce..ba49a2d58 100644
--- a/components/signin/public/identity_manager/identity_test_environment.h
+++ b/components/signin/public/identity_manager/identity_test_environment.h
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/optional.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -366,7 +367,7 @@
   void Initialize();
 
   // Create an IdentityManager instance for tests.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests(
       SigninClient* signin_client,
       PrefService* pref_service,
diff --git a/components/signin/public/identity_manager/identity_test_utils.cc b/components/signin/public/identity_manager/identity_test_utils.cc
index e440df0..1606d7b7 100644
--- a/components/signin/public/identity_manager/identity_test_utils.cc
+++ b/components/signin/public/identity_manager/identity_test_utils.cc
@@ -9,6 +9,7 @@
 #include "base/guid.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
 #include "components/signin/internal/identity_manager/primary_account_manager.h"
@@ -21,7 +22,7 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chromeos/components/account_manager/account_manager.h"
 #include "components/account_manager_core/account.h"
 #endif
@@ -57,7 +58,7 @@
 void UpdateRefreshTokenForAccount(
     ProfileOAuth2TokenService* token_service,
     AccountTrackerService* account_tracker_service,
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::AccountManager* account_manager,
 #endif
     IdentityManager* identity_manager,
@@ -79,7 +80,7 @@
   token_updated_observer.SetOnRefreshTokenUpdatedCallback(
       run_loop.QuitClosure());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const AccountInfo& account_info =
       account_tracker_service->GetAccountInfo(account_id);
 
@@ -191,7 +192,7 @@
 
 void ClearPrimaryAccount(IdentityManager* identity_manager,
                          ClearPrimaryAccountPolicy policy) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO(blundell): If we ever need this functionality on ChromeOS (which seems
   // unlikely), plumb this through to just clear the primary account info
   // synchronously with IdentityManager.
@@ -300,12 +301,12 @@
   UpdateRefreshTokenForAccount(
       identity_manager->GetTokenService(),
       identity_manager->GetAccountTrackerService(),
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
       identity_manager->GetChromeOSAccountManager(),
 #endif
       identity_manager, account_id,
-      token_value.empty() ? "refresh_token_for_" + account_id.ToString()
-                                + "_" + base::GenerateGUID()
+      token_value.empty() ? "refresh_token_for_" + account_id.ToString() + "_" +
+                                base::GenerateGUID()
                           : token_value);
 }
 
@@ -314,7 +315,7 @@
   UpdateRefreshTokenForAccount(identity_manager->GetTokenService(),
 
                                identity_manager->GetAccountTrackerService(),
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
                                identity_manager->GetChromeOSAccountManager(),
 #endif
                                identity_manager, account_id,
@@ -331,7 +332,7 @@
   token_updated_observer.SetOnRefreshTokenRemovedCallback(
       run_loop.QuitClosure());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const AccountInfo& account_info =
       identity_manager->GetAccountTrackerService()->GetAccountInfo(account_id);
 
diff --git a/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc b/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
index dfa9378..2478e85 100644
--- a/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
+++ b/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/identity_manager/access_token_info.h"
 #include "components/signin/public/identity_manager/consent_level.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
@@ -329,7 +330,7 @@
       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
 }
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_P(PrimaryAccountAccessTokenFetcherTest,
        ShouldNotRetryCanceledAccessTokenRequestIfSignedOut) {
@@ -406,7 +407,7 @@
                          testing::Values(ConsentLevel::kNotRequired,
                                          ConsentLevel::kSync));
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Chrome OS can directly set the unconsented primary account during login,
 // so it has additional tests.
 TEST_F(PrimaryAccountAccessTokenFetcherTest,
@@ -467,6 +468,6 @@
       access_token_info().token, access_token_info().expiration_time,
       access_token_info().id_token);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace signin
diff --git a/components/signin/public/identity_manager/primary_account_mutator.h b/components/signin/public/identity_manager/primary_account_mutator.h
index 40252a3..feb55a4 100644
--- a/components/signin/public/identity_manager/primary_account_mutator.h
+++ b/components/signin/public/identity_manager/primary_account_mutator.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace signin_metrics {
 enum ProfileSignout : int;
@@ -66,7 +67,7 @@
   virtual void SetUnconsentedPrimaryAccount(
       const CoreAccountId& account_id) = 0;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Revokes sync consent from the primary account. The primary account must
   // have sync consent. After the call a primary account will remain but it will
   // not have sync consent.
@@ -74,7 +75,7 @@
   virtual void RevokeSyncConsent() = 0;
 #endif
 
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Clears the primary account, and returns whether the operation
   // succeeded or not. Depending on |action|, the other accounts
   // known to the IdentityManager may be deleted.
diff --git a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
index 11784e17..136ff2b 100644
--- a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/scoped_observation.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "components/signin/public/base/signin_pref_names.h"
 #include "components/signin/public/identity_manager/consent_level.h"
@@ -24,7 +25,7 @@
 
 // Constants used by the different tests.
 const char kPrimaryAccountEmail[] = "primary.account@example.com";
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 const char kAnotherAccountEmail[] = "another.account@example.com";
 const char kUnknownAccountId[] = "{unknown account id}";
 
@@ -211,7 +212,7 @@
       break;
   }
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
 
@@ -247,7 +248,7 @@
 // ChromeOS, where those preconditions do not exist.
 // TODO(https://crbug.com/983124): Run these tests on ChromeOS if/once we
 // enable those preconditions on that platform
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 // Checks that setting the primary account fails if the account is not known by
 // the identity system.
 TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_NoAccount) {
@@ -351,14 +352,14 @@
   EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
       primary_account_info.account_id));
 }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // End of tests of preconditions not being satisfied causing the setting of
 // the primary account to fail.
 
 // Tests of clearing the primary account. Not run on ChromeOS, which does not
 // support clearing the primary account.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_NotSignedIn) {
   base::test::TaskEnvironment task_environment;
   signin::IdentityTestEnvironment environment;
@@ -506,9 +507,9 @@
       RemoveAccountExpectation::kRemovePrimary, AuthExpectation::kAuthError);
 }
 #endif  // !defined(OS_ANDROID)
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PrimaryAccountMutatorTest, RevokeSyncConsent) {
   base::test::TaskEnvironment task_environment;
   signin::IdentityTestEnvironment environment;
@@ -535,4 +536,4 @@
 
   identity_manager->RemoveObserver(&observer);
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc
index 9d76d7f..bb758777 100644
--- a/components/sync/engine_impl/loopback_server/loopback_server.cc
+++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -870,24 +870,33 @@
 
 bool LoopbackServer::LoadStateFromFile() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!base::PathExists(persistent_file_)) {
-    LOG(WARNING) << "Loopback sync persistent state file does not exist.";
+
+  // Ensures local sync file can be opened, read, and is not being written to.
+  // Also makes sure file will not be written to during serialization.
+  base::File state_file(persistent_file_, base::File::FLAG_OPEN |
+                                              base::File::FLAG_READ |
+                                              base::File::FLAG_EXCLUSIVE_WRITE);
+  base::File::Error state_file_error = state_file.error_details();
+
+  if (state_file_error != base::File::FILE_OK) {
+    UMA_HISTOGRAM_ENUMERATION("Sync.Local.ReadPlatformFileError",
+                              -state_file_error, -base::File::FILE_ERROR_MAX);
+    LOG(ERROR)
+        << "Loopback sync cannot read the persistent state file with error "
+        << base::File::ErrorToString(state_file_error);
     return false;
   }
+
   std::string serialized;
   if (base::ReadFileToString(persistent_file_, &serialized)) {
     sync_pb::LoopbackServerProto proto;
     if (serialized.length() > 0 && proto.ParseFromString(serialized)) {
       return DeSerializeState(proto);
     }
-    LOG(ERROR) << "Loopback sync can not parse the persistent state file.";
+    LOG(ERROR) << "Loopback sync cannot parse the persistent state file.";
     return false;
   }
-  // TODO(pastarmovj): Try to understand what is the issue e.g. file already
-  // open, no access rights etc. and decide if better course of action is
-  // available instead of giving up and wiping the global state on the next
-  // write.
-  LOG(ERROR) << "Loopback sync can not read the persistent state file.";
+  LOG(ERROR) << "Loopback sync cannot read the persistent state file.";
   return false;
 }
 
diff --git a/components/test/data/web_package/generate-test-wbns.sh b/components/test/data/web_package/generate-test-wbns.sh
index 5e85db9..fcacc32 100755
--- a/components/test/data/web_package/generate-test-wbns.sh
+++ b/components/test/data/web_package/generate-test-wbns.sh
@@ -10,6 +10,7 @@
     if ! command -v $cmd > /dev/null 2>&1; then
         echo "$cmd is not installed. Please run:"
         echo "  go get -u github.com/WICG/webpackage/go/bundle/cmd/..."
+        echo '  export PATH=$PATH:$(go env GOPATH)/bin'
         exit 1
     fi
 done
diff --git a/components/ukm/content/source_url_recorder.cc b/components/ukm/content/source_url_recorder.cc
index 47614098..92720e93 100644
--- a/components/ukm/content/source_url_recorder.cc
+++ b/components/ukm/content/source_url_recorder.cc
@@ -54,11 +54,6 @@
       public content::WebContentsUserData<
           SourceUrlRecorderWebContentsObserver> {
  public:
-  // Creates a SourceUrlRecorderWebContentsObserver for the given
-  // WebContents. If a SourceUrlRecorderWebContentsObserver is already
-  // associated with the WebContents, this method is a no-op.
-  static void CreateForWebContents(content::WebContents* web_contents);
-
   // content::WebContentsObserver:
   void DidStartNavigation(
       content::NavigationHandle* navigation_handle) override;
@@ -344,17 +339,6 @@
   ukm_recorder->RecordNavigation(source_id, navigation_data);
 }
 
-// static
-void SourceUrlRecorderWebContentsObserver::CreateForWebContents(
-    content::WebContents* web_contents) {
-  if (!SourceUrlRecorderWebContentsObserver::FromWebContents(web_contents)) {
-    web_contents->SetUserData(
-        SourceUrlRecorderWebContentsObserver::UserDataKey(),
-        base::WrapUnique(
-            new SourceUrlRecorderWebContentsObserver(web_contents)));
-  }
-}
-
 }  // namespace internal
 
 void InitializeSourceUrlRecorderForWebContents(
diff --git a/components/viz/common/gpu/vulkan_context_provider.h b/components/viz/common/gpu/vulkan_context_provider.h
index fc823ba..70ab11d 100644
--- a/components/viz/common/gpu/vulkan_context_provider.h
+++ b/components/viz/common/gpu/vulkan_context_provider.h
@@ -12,6 +12,7 @@
 #include "components/viz/common/viz_vulkan_context_provider_export.h"
 #include "third_party/vulkan_headers/include/vulkan/vulkan.h"
 
+struct GrContextOptions;
 class GrDirectContext;
 class GrVkSecondaryCBDrawContext;
 
@@ -26,6 +27,7 @@
 class VIZ_VULKAN_CONTEXT_PROVIDER_EXPORT VulkanContextProvider
     : public base::RefCountedThreadSafe<VulkanContextProvider> {
  public:
+  virtual bool InitializeGrContext(const GrContextOptions& context_options) = 0;
   virtual gpu::VulkanImplementation* GetVulkanImplementation() = 0;
   virtual gpu::VulkanDeviceQueue* GetDeviceQueue() = 0;
   virtual GrDirectContext* GetGrContext() = 0;
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.cc b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
index 0a30603f..292409d 100644
--- a/components/viz/common/gpu/vulkan_in_process_context_provider.cc
+++ b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
@@ -23,11 +23,10 @@
 scoped_refptr<VulkanInProcessContextProvider>
 VulkanInProcessContextProvider::Create(
     gpu::VulkanImplementation* vulkan_implementation,
-    const GrContextOptions& options,
     const gpu::GPUInfo* gpu_info) {
   scoped_refptr<VulkanInProcessContextProvider> context_provider(
       new VulkanInProcessContextProvider(vulkan_implementation));
-  if (!context_provider->Initialize(options, gpu_info))
+  if (!context_provider->Initialize(gpu_info))
     return nullptr;
   return context_provider;
 }
@@ -41,7 +40,6 @@
 }
 
 bool VulkanInProcessContextProvider::Initialize(
-    const GrContextOptions& context_options,
     const gpu::GPUInfo* gpu_info) {
   DCHECK(!device_queue_);
 
@@ -64,6 +62,11 @@
   if (!device_queue_)
     return false;
 
+  return true;
+}
+
+bool VulkanInProcessContextProvider::InitializeGrContext(
+    const GrContextOptions& context_options) {
   GrVkBackendContext backend_context;
   backend_context.fInstance = device_queue_->GetVulkanInstance();
   backend_context.fPhysicalDevice = device_queue_->GetVulkanPhysicalDevice();
@@ -86,6 +89,10 @@
     return vkGetInstanceProcAddr(instance, proc_name);
   };
 
+  const auto& instance_extensions = vulkan_implementation_->GetVulkanInstance()
+                                        ->vulkan_info()
+                                        .enabled_instance_extensions;
+
   std::vector<const char*> device_extensions;
   device_extensions.reserve(device_queue_->enabled_extensions().size());
   for (const auto& extension : device_queue_->enabled_extensions())
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.h b/components/viz/common/gpu/vulkan_in_process_context_provider.h
index ec6676e..9b2a787a 100644
--- a/components/viz/common/gpu/vulkan_in_process_context_provider.h
+++ b/components/viz/common/gpu/vulkan_in_process_context_provider.h
@@ -30,12 +30,12 @@
  public:
   static scoped_refptr<VulkanInProcessContextProvider> Create(
       gpu::VulkanImplementation* vulkan_implementation,
-      const GrContextOptions& context_options = GrContextOptions(),
       const gpu::GPUInfo* gpu_info = nullptr);
 
   void Destroy();
 
   // VulkanContextProvider implementation
+  bool InitializeGrContext(const GrContextOptions& context_options) override;
   gpu::VulkanImplementation* GetVulkanImplementation() override;
   gpu::VulkanDeviceQueue* GetDeviceQueue() override;
   GrDirectContext* GetGrContext() override;
@@ -49,8 +49,7 @@
       gpu::VulkanImplementation* vulkan_implementation);
   ~VulkanInProcessContextProvider() override;
 
-  bool Initialize(const GrContextOptions& context_options,
-                  const gpu::GPUInfo* gpu_info);
+  bool Initialize(const gpu::GPUInfo* gpu_info);
 
 #if BUILDFLAG(ENABLE_VULKAN)
   sk_sp<GrDirectContext> gr_context_;
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index 9a04a1b..46e1180 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -74,12 +74,12 @@
     const AggregatedRenderPassDrawQuad* rpdq,
     float max_pixel_movement) {
   const SharedQuadState* shared_quad_state = rpdq->shared_quad_state;
-  gfx::Rect expanded_rect = rpdq->rect;
+  gfx::RectF expanded_rect(rpdq->rect);
   expanded_rect.Inset(-max_pixel_movement, -max_pixel_movement);
 
   // expanded_rect in the target space
   return cc::MathUtil::MapClippedRect(
-      shared_quad_state->quad_to_target_transform, gfx::RectF(expanded_rect));
+      shared_quad_state->quad_to_target_transform, expanded_rect);
 }
 
 DCLayerResult ValidateYUVQuad(
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 0b6b77f..1a0e760 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -85,8 +85,9 @@
     const CompositorRenderPass& child_render_pass) {
   const SharedQuadState* shared_quad_state = rpdq->shared_quad_state;
   float max_pixel_movement = child_render_pass.filters.MaximumPixelMovement();
-  gfx::Rect expanded_rect = rpdq->rect;
-  expanded_rect.Inset(-max_pixel_movement, -max_pixel_movement);
+  gfx::RectF rect(rpdq->rect);
+  rect.Inset(-max_pixel_movement, -max_pixel_movement);
+  gfx::Rect expanded_rect = gfx::ToEnclosingRect(rect);
 
   // expanded_rect in the target space
   return cc::MathUtil::MapEnclosingClippedRect(
@@ -277,7 +278,9 @@
   gfx::Rect damage_rect = source_pass->output_rect;
   if (source_pass->filters.HasFilterThatMovesPixels()) {
     float max_pixel_movement = source_pass->filters.MaximumPixelMovement();
-    damage_rect.Inset(-max_pixel_movement, -max_pixel_movement);
+    gfx::RectF damage_rect_f(damage_rect);
+    damage_rect_f.Inset(-max_pixel_movement, -max_pixel_movement);
+    damage_rect = gfx::ToEnclosingRect(damage_rect_f);
   }
 
   gfx::Rect damage_rect_in_root_target_space =
@@ -288,6 +291,8 @@
   // backdrop filters is considered damaged if it intersects with the other
   // damages.
   if (damage_rect_in_root_target_space.Intersects(root_damage_rect_)) {
+    // Transform will be performed again in AddSurfaceDamageToDamageList()
+    // Just pass in damage_rect instead of damage_rect_in_root_target_space.
     AddSurfaceDamageToDamageList(damage_rect, gfx::Transform(), {}, source_pass,
                                  dest_pass, /*surface=*/nullptr);
   }
diff --git a/components/viz/service/display_embedder/output_presenter_fuchsia.cc b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
index 6e8c662..96d05fa 100644
--- a/components/viz/service/display_embedder/output_presenter_fuchsia.cc
+++ b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
@@ -421,12 +421,12 @@
   for (size_t i = 0; i < overlays.size(); ++i) {
     next_frame_->overlays.emplace_back(std::move(overlays[i]),
                                        accesses[i]->TakeReleaseFences());
-    // Merge all fences under |acquire_fences|, because we are trying to sync
-    // primary plane and overlay updates to avoid artifacts.
-    for (auto& fence : accesses[i]->TakeAcquireFences()) {
-      next_frame_->acquire_fences.push_back(
-          std::move(fence.GetGpuFenceHandle().Clone().owned_event));
-    }
+    // TODO(crbug.com/1144890): Enqueue overlay plane's acquire fences
+    // after |supports_commit_overlay_planes| is supported. Overlay plane might
+    // display the same Image more than once, which can create a fence
+    // dependency that can be broken by a later Image. However, primary plane
+    // implementation allows only one present at a time. In this scenario,
+    // merging fences might cause hangs, see crbug.com/1151042.
   }
 }
 
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 4c35b56..1d42308 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -369,7 +369,7 @@
     // If GL is using a real GPU, the gpu_info will be passed in and vulkan will
     // use the same GPU.
     vulkan_context_provider_ = VulkanInProcessContextProvider::Create(
-        vulkan_implementation_, context_options,
+        vulkan_implementation_,
         (is_native_vulkan && is_native_gl) ? &gpu_info : nullptr);
     if (vulkan_context_provider_) {
       // If Vulkan is supported, then OOP-R is supported.
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 05a3ada..13df3f1 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -8556,4 +8556,38 @@
       FROM_HERE);
 }
 
+class BackForwardCacheBrowserTestWithFileSystemAPISupported
+    : public BackForwardCacheBrowserTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    EnableFeatureAndSetParams(features::kBackForwardCache,
+                              "file_system_api_supported", "true");
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithFileSystemAPISupported,
+                       CacheWithFileSystemAPI) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a(embedded_test_server()->GetURL("/fileapi/request_test.html"));
+  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+  // 1) Navigate to a page with WebFileSystem usage.
+  EXPECT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImpl* rfh_a = current_frame_host();
+  RenderFrameDeletedObserver deleted(rfh_a);
+
+  // 2) Navigate away.
+  EXPECT_TRUE(NavigateToURL(shell(), url_b));
+  EXPECT_FALSE(deleted.deleted());
+  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
+
+  // 3) Go back to the page with WebFileSystem.
+  web_contents()->GetController().GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  EXPECT_EQ(rfh_a, current_frame_host());
+  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
+                FROM_HERE);
+}
+
 }  // namespace content
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc
index 21b4611f..6ef2edef 100644
--- a/content/browser/cross_origin_opener_policy_browsertest.cc
+++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -1970,8 +1971,16 @@
   EXPECT_NE(group_4, group_1);
 }
 
+// This test is flaky on Win: https://crbug.com/1125998.
+#if defined(OS_WIN)
+#define MAYBE_CrossOriginIsolatedSiteInstance_MainFrame \
+  DISABLED_CrossOriginIsolatedSiteInstance_MainFrame
+#else
+#define MAYBE_CrossOriginIsolatedSiteInstance_MainFrame \
+  CrossOriginIsolatedSiteInstance_MainFrame
+#endif
 IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest,
-                       CrossOriginIsolatedSiteInstance_MainFrame) {
+                       MAYBE_CrossOriginIsolatedSiteInstance_MainFrame) {
   GURL isolated_page(
       https_server()->GetURL("a.com",
                              "/set-header?"
diff --git a/content/browser/media/media_devices_util.cc b/content/browser/media/media_devices_util.cc
index ae0e5c6e..48c4be6 100644
--- a/content/browser/media/media_devices_util.cc
+++ b/content/browser/media/media_devices_util.cc
@@ -198,7 +198,7 @@
       has_permission ? device_info.video_control_support
                      : media::VideoCaptureControlSupport(),
       has_permission ? device_info.video_facing
-                     : media::MEDIA_VIDEO_FACING_NONE);
+                     : blink::mojom::FacingMode::NONE);
 }
 
 blink::WebMediaDeviceInfoArray TranslateMediaDeviceInfoArray(
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc
index e9b04931..6335c6a 100644
--- a/content/browser/renderer_host/back_forward_cache_impl.cc
+++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -88,6 +88,14 @@
   return geolocation_supported.Get();
 }
 
+bool IsFileSystemSupported() {
+  if (!DeviceHasEnoughMemoryForBackForwardCache())
+    return false;
+  static constexpr base::FeatureParam<bool> file_system_api_supported(
+      &features::kBackForwardCache, "file_system_api_supported", false);
+  return file_system_api_supported.Get();
+}
+
 bool IgnoresOutstandingNetworkRequestForTesting() {
   if (!DeviceHasEnoughMemoryForBackForwardCache())
     return false;
@@ -146,7 +154,6 @@
       FeatureToBit(WebSchedulerTrackedFeature::kSpeechSynthesis) |
       FeatureToBit(WebSchedulerTrackedFeature::kWakeLock) |
       FeatureToBit(WebSchedulerTrackedFeature::kWebDatabase) |
-      FeatureToBit(WebSchedulerTrackedFeature::kWebFileSystem) |
       FeatureToBit(WebSchedulerTrackedFeature::kWebHID) |
       FeatureToBit(WebSchedulerTrackedFeature::kWebLocks) |
       FeatureToBit(WebSchedulerTrackedFeature::kWebRTC) |
@@ -171,6 +178,10 @@
         FeatureToBit(WebSchedulerTrackedFeature::kOutstandingNetworkRequestXHR);
   }
 
+  if (!IsFileSystemSupported()) {
+    result |= FeatureToBit(WebSchedulerTrackedFeature::kWebFileSystem);
+  }
+
   if (requested_features == RequestedFeatures::kOnlySticky) {
     // Remove all non-sticky features from |result|.
     result &= blink::scheduler::StickyFeaturesBitmask();
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 32559d1..2ee2179f6 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -38,6 +38,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/audio/public/mojom/device_notifications.mojom.h"
 #include "third_party/blink/public/common/mediastream/media_devices.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
 
 #if defined(OS_MAC)
 #include "base/callback_helpers.h"
@@ -933,10 +934,9 @@
 
   blink::WebMediaDeviceInfoArray snapshot;
   for (const media::AudioDeviceDescription& description : device_descriptions) {
-    snapshot.emplace_back(description.unique_id, description.device_name,
-                          description.group_id,
-                          media::VideoCaptureControlSupport(),
-                          media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE);
+    snapshot.emplace_back(
+        description.unique_id, description.device_name, description.group_id,
+        media::VideoCaptureControlSupport(), blink::mojom::FacingMode::NONE);
   }
   DevicesEnumerated(type, snapshot);
 }
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 76dbe31..107cbdc 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -2630,9 +2630,9 @@
     const blink::WebMediaDeviceInfoArray& device_infos) {
   MediaStreamDevices devices;
   for (const auto& info : device_infos) {
-    devices.emplace_back(stream_type, info.device_id, info.label,
-                         info.video_control_support, info.video_facing,
-                         info.group_id);
+    devices.emplace_back(
+        stream_type, info.device_id, info.label, info.video_control_support,
+        static_cast<media::VideoFacingMode>(info.video_facing), info.group_id);
   }
 
   return devices;
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 4cb4a1b..b656744 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -704,8 +704,6 @@
   // This can happen during destruction after the RFH has been cleared.
   if (!render_frame_host_)
     return;
-  if (render_frame_host_->must_be_replaced())
-    return;
   if (!speculative_render_frame_host_)
     return;
   if (speculative_render_frame_host_->GetSiteInstance() ==
@@ -722,7 +720,9 @@
     SCOPED_CRASH_KEY_STRING256(
         ValidateSpeculative, NewSiteInstance,
         speculative_render_frame_host_->GetSiteInstance()->GetSiteURL().spec());
-    DCHECK(false);
+    SCOPED_CRASH_KEY_BOOL(ValidateSpeculative, MustBeReplaced,
+                          render_frame_host_->must_be_replaced());
+    NOTREACHED();
     base::debug::DumpWithoutCrashing();
   }
 }
@@ -2394,7 +2394,6 @@
 
   speculative_render_frame_host_ = CreateSpeculativeRenderFrame(
       new_instance, recovering_without_early_commit);
-  ValidateSpeculativeRenderFrameHostForBug1146573();
 
   // If RenderViewHost was created along with the speculative RenderFrameHost,
   // ensure that RenderViewCreated is fired for it.  It is important to do this
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 0f7426de..8d9b8dc 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -92,7 +92,9 @@
       public aura::client::FocusChangeObserver,
       public aura::client::CursorClientObserver {
  public:
-  RenderWidgetHostViewAura(RenderWidgetHost* host);
+  explicit RenderWidgetHostViewAura(RenderWidgetHost* host);
+  RenderWidgetHostViewAura(const RenderWidgetHostViewAura&) = delete;
+  RenderWidgetHostViewAura& operator=(const RenderWidgetHostViewAura&) = delete;
 
   // RenderWidgetHostView implementation.
   void InitAsChild(gfx::NativeView parent_view) override;
@@ -715,8 +717,6 @@
   base::Optional<DisplayFeature> display_feature_;
 
   base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
 };
 
 }  // namespace content
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 45a5da9..f91e9ed 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -74,6 +74,9 @@
 // Basic implementation shared by concrete RenderWidgetHostView subclasses.
 class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
  public:
+  RenderWidgetHostViewBase(const RenderWidgetHostViewBase&) = delete;
+  RenderWidgetHostViewBase& operator=(const RenderWidgetHostViewBase&) = delete;
+
   float current_device_scale_factor() const {
     return current_device_scale_factor_;
   }
@@ -518,6 +521,7 @@
 
  protected:
   explicit RenderWidgetHostViewBase(RenderWidgetHost* host);
+  ~RenderWidgetHostViewBase() override;
 
   void NotifyObserversAboutShutdown();
 
@@ -586,9 +590,6 @@
 
   bool is_currently_scrolling_viewport_ = false;
 
- protected:
-  ~RenderWidgetHostViewBase() override;
-
  private:
   FRIEND_TEST_ALL_PREFIXES(
       BrowserSideFlingBrowserTest,
@@ -642,8 +643,6 @@
   bool is_evicted_ = false;
 
   base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
 };
 
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_user_data_unittest.cc b/content/browser/web_contents/web_contents_user_data_unittest.cc
index cd8a828..a01df353 100644
--- a/content/browser/web_contents/web_contents_user_data_unittest.cc
+++ b/content/browser/web_contents/web_contents_user_data_unittest.cc
@@ -111,4 +111,56 @@
   ASSERT_EQ(clazz, class_again);
 }
 
+class NonCopyableNonMovableClass {
+ public:
+  explicit NonCopyableNonMovableClass(int value) : value_(value) {}
+
+  NonCopyableNonMovableClass(const NonCopyableNonMovableClass&) = delete;
+  NonCopyableNonMovableClass& operator=(const NonCopyableNonMovableClass&) =
+      delete;
+  NonCopyableNonMovableClass(NonCopyableNonMovableClass&&) = delete;
+  NonCopyableNonMovableClass& operator=(NonCopyableNonMovableClass&&) = delete;
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+class AttachedClassWithParams
+    : public WebContentsUserData<AttachedClassWithParams> {
+ public:
+  ~AttachedClassWithParams() override = default;
+
+  int param1() const { return param1_; }
+  int param2() const { return param2_; }
+
+ private:
+  friend class WebContentsUserData<AttachedClassWithParams>;
+
+  explicit AttachedClassWithParams(WebContents* contents,
+                                   int param1,
+                                   NonCopyableNonMovableClass&& param2)
+      : param1_(param1), param2_(param2.value()) {}
+
+  int param1_;
+  int param2_;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(AttachedClassWithParams)
+
+TEST_F(WebContentsUserDataTest, CreateWithParameters) {
+  ASSERT_EQ(nullptr, AttachedClassWithParams::FromWebContents(web_contents()));
+
+  AttachedClassWithParams::CreateForWebContents(web_contents(), 1,
+                                                NonCopyableNonMovableClass(42));
+  auto* instance = AttachedClassWithParams::FromWebContents(web_contents());
+  ASSERT_NE(nullptr, instance);
+
+  EXPECT_EQ(1, instance->param1());
+  EXPECT_EQ(42, instance->param2());
+}
+
 }  // namespace content
diff --git a/content/browser/web_package/signed_exchange_handler_unittest.cc b/content/browser/web_package/signed_exchange_handler_unittest.cc
index f511bcc..cfa20744 100644
--- a/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -32,7 +32,6 @@
 #include "net/base/network_isolation_key.h"
 #include "net/base/test_completion_callback.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/cert/sct_auditing_delegate.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
@@ -66,15 +65,8 @@
 
 constexpr char kTestSxgInnerURL[] = "https://test.example.org/test/";
 
-// "wildcard_example.org.public.pem.cbor" has these dummy data in "ocsp" and
-// "sct" fields.
+// "wildcard_example.org.public.pem.cbor" has dummy data in its "ocsp" field.
 constexpr base::StringPiece kDummyOCSPDer = "OCSP";
-constexpr char kDummySCTBytes[] = {
-    0x00, 0x05,                // Length of the sct list
-    0x00, 0x03, 'S', 'C', 'T'  // List entry: length and body
-};
-constexpr base::StringPiece kDummySCTList(kDummySCTBytes,
-                                          sizeof(kDummySCTBytes));
 
 // ExpectCTReporter implementation that logs a single report.
 class MockExpectCTReporter
@@ -185,17 +177,6 @@
   MOCK_METHOD1(SetConfig, void(const net::CertVerifier::Config& config));
 };
 
-class MockCTVerifier : public net::CTVerifier {
- public:
-  MOCK_METHOD6(Verify,
-               void(base::StringPiece hostname,
-                    net::X509Certificate* cert,
-                    base::StringPiece stapled_ocsp_response,
-                    base::StringPiece sct_list_from_tls_extension,
-                    net::SignedCertificateTimestampAndStatusList* output_scts,
-                    const net::NetLogWithSource& net_log));
-};
-
 class MockCTPolicyEnforcer : public net::CTPolicyEnforcer {
  public:
   MOCK_METHOD3(
@@ -433,7 +414,6 @@
   const base::HistogramTester histogram_tester_;
   MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
   std::unique_ptr<net::CertVerifier> cert_verifier_;
-  std::unique_ptr<MockCTVerifier> mock_ct_verifier_;
   std::unique_ptr<MockCTPolicyEnforcer> mock_ct_policy_enforcer_;
   std::unique_ptr<MockSCTAuditingDelegate> mock_sct_auditing_delegate_;
   net::MockSourceStream* source_;
@@ -1089,8 +1069,8 @@
   EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
 }
 
-// Test that SignedExchangeHandler calls CTVerifier and CTPolicyEnforcer
-// with appropriate arguments.
+// Test that SignedExchangeHandler calls CTPolicyEnforcer with appropriate
+// arguments.
 TEST_P(SignedExchangeHandlerTest, CTVerifierParams) {
   mock_cert_fetcher_factory_->ExpectFetch(
       GURL("https://cert.example.org/cert.msg"),
@@ -1110,23 +1090,17 @@
       .WillOnce(
           Return(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
 
-  mock_ct_verifier_ = std::make_unique<MockCTVerifier>();
-  EXPECT_CALL(*mock_ct_verifier_,
-              Verify(base::StringPiece("test.example.org"),
-                     CertEqualsIncludingChain(original_cert), kDummyOCSPDer,
-                     kDummySCTList, _ /* output_scts */, _ /* net_log */))
-      .WillOnce(SetArgPointee<4>(fake_sct_list));
-
   auto test_url_request_context = std::make_unique<net::TestURLRequestContext>(
       true /* delay_initialization */);
   test_url_request_context->set_ct_policy_enforcer(
       mock_ct_policy_enforcer_.get());
-  test_url_request_context->set_cert_transparency_verifier(
-      mock_ct_verifier_.get());
   test_url_request_context->Init();
 
-  SetupMockCertVerifier("prime256v1-sha256.public.pem",
-                        CreateCertVerifyResult());
+  // Mock a verify result including the SCTs.
+  auto verify_result = CreateCertVerifyResult();
+  verify_result.scts = fake_sct_list;
+  SetupMockCertVerifier("prime256v1-sha256.public.pem", verify_result);
+
   std::string contents = GetTestFileContents("test.example.org_test.sxg");
   source_->AddReadResult(contents.data(), contents.size(), net::OK,
                          net::MockSourceStream::ASYNC);
@@ -1181,44 +1155,6 @@
   EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
 }
 
-// Test that SignedExchangeHandler does not enqueue SCT auditing reports if the
-// certificate is not issued by a known root. Mirrors the
-// `SCTAuditingReportEnqueued` test above, except that `is_issued_by_known_root`
-// is set to false.
-TEST_P(SignedExchangeHandlerTest, SCTAuditingReportNonPublicCertsNotReported) {
-  mock_cert_fetcher_factory_->ExpectFetch(
-      GURL("https://cert.example.org/cert.msg"),
-      GetTestFileContents("test.example.org.public.pem.cbor"));
-
-  net::CertVerifyResult cert_result = CreateCertVerifyResult();
-  cert_result.is_issued_by_known_root = false;
-  SetupMockCertVerifier("prime256v1-sha256.public.pem", cert_result);
-
-  // The mock CT policy enforcer will return CT_POLICY_COMPLIES_VIA_SCTS, as
-  // configured in SetUp().
-
-  // Add SCTAuditingDelegate mock results.
-  EXPECT_CALL(*mock_sct_auditing_delegate_, IsSCTAuditingEnabled())
-      .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_sct_auditing_delegate_, MaybeEnqueueReport(_, _, _))
-      .Times(0);
-
-  SetSourceStreamContents("test.example.org_test.sxg");
-
-  CreateSignedExchangeHandler(CreateTestURLRequestContext());
-  WaitForHeader();
-
-  ASSERT_TRUE(read_header());
-  EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
-  EXPECT_EQ(net::OK, error());
-
-  std::string payload;
-  int rv = ReadPayloadStream(&payload);
-  std::string expected_payload = GetTestFileContents("test.html");
-  EXPECT_EQ(expected_payload, payload);
-  EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
-}
-
 INSTANTIATE_TEST_SUITE_P(SignedExchangeHandlerTests,
                          SignedExchangeHandlerTest,
                          ::testing::Values(net::MockSourceStream::SYNC,
diff --git a/content/public/browser/web_contents_user_data.h b/content/public/browser/web_contents_user_data.h
index 6f5718e..9d9ed27b 100644
--- a/content/public/browser/web_contents_user_data.h
+++ b/content/public/browser/web_contents_user_data.h
@@ -34,10 +34,14 @@
  public:
   // Creates an object of type T, and attaches it to the specified WebContents.
   // If an instance is already attached, does nothing.
-  static void CreateForWebContents(WebContents* contents) {
+  template <typename... Args>
+  static void CreateForWebContents(WebContents* contents, Args&&... args) {
     DCHECK(contents);
-    if (!FromWebContents(contents))
-      contents->SetUserData(UserDataKey(), base::WrapUnique(new T(contents)));
+    if (!FromWebContents(contents)) {
+      contents->SetUserData(
+          UserDataKey(),
+          base::WrapUnique(new T(contents, std::forward<Args>(args)...)));
+    }
   }
 
   // Retrieves the instance of type T that was attached to the specified
diff --git a/content/public/test/README.md b/content/public/test/README.md
new file mode 100644
index 0000000..23856cc
--- /dev/null
+++ b/content/public/test/README.md
@@ -0,0 +1,193 @@
+# Content Browser Test Tips
+
+A random collection of useful things to know when writing browser tests.
+
+[TOC]
+
+## Executing JavaScript
+
+If the test needs to use the return value of the script, use `EvalJs()`:
+
+```c++
+  // Works with numerical types...
+  EXPECT_EQ(0, EvalJs(shell(), "1 * 0");
+
+  // ... string types ...
+  EXPECT_EQ("BODY", EvalJs(shell(), "document.body.tagName");
+
+  // and booleans too. Note the explicit use of EXPECT_EQ() instead of
+  // EXPECT_TRUE() or EXPECT_FALSE(); this is intentional, and the latter
+  // will not compile.
+  EXPECT_EQ(false, EvalJs(shell(), "2 + 2 == 5"));
+```
+
+Like many other test helpers (e.g. the navigation helpers), the first argument
+accepts `RenderFrameHost`, `WebContents`, and other types.
+
+```c++
+  // Executes in the main frame.
+  EXPECT_EQ(true, EvalJs(shell()->GetWebContents(), "window.top == window"));
+
+  // Also executes in the main frame.
+  EXPECT_EQ(true, EvalJs(shell(), "window.top == window"));
+
+  // Executes in the first child frame of the main frame.
+  EXPECT_EQ(
+      false,
+      EvalJs(ChildFrameAt(shell()->GetWebContents()->GetMainFrame(), 0),
+             "window.top == window"));
+```
+
+Otherwise, simply use `ExecJs()`:
+
+```c++
+  EXPECT_TRUE(ExecJs("console.log('Hello world!')"));
+```
+
+Note that these helpers block until the script completes. For async
+execution, use `ExecuteScriptAsync()`.
+
+Finally, `JsReplace()` provides a convenient way to build strings for script
+execution:
+
+```c++
+  EXPECT_EQ("00", EvalJs(JsReplace("$1 + $2", 0, "0")));
+```
+
+## Cross-origin navigations
+
+For cross-origin navigations, it is to simplest to configure all hostnames to
+resolve to `127.0.0.1` in tests, using a snippet like this:
+
+```c++
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+```
+
+After that, `EmbeddedTestServer::GetURL()` can be used to generate navigable
+URLs with the specific origin:
+
+```c++
+  const GURL& url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
+  const GURL& url_b = embedded_test_server()->GetURL("b.com", "/empty.html");
+```
+
+Most test resources are located in `//content/test/data`, e.g. navigating to
+`GetURL("a.com", "/title1.html")` will serve `//content/test/data/title1.html`
+as the content.
+
+## Browser-initiated navigation to a specific origin
+
+> **Note:** using arbitrary hostnames requires the [host resolver to
+> be correctly configured][host-resolver-config].
+
+`NavigateToURL()` begins and waits for the navigation to complete, as if the
+navigation was browser-initiated, e.g. from the omnibox:
+
+```c++
+  GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+```
+
+> **Note**: NavigateToURL() allows subframes to be targetted, but outside of history
+> navigations, subframe navigations are generally _renderer-initiated_.
+
+## Renderer-initiated navigation to a specific origin
+
+> **Note:** using arbitrary hostnames requires the [host resolver to
+> be correctly configured][host-resolver-config].
+
+`NavigateToURLFromRenderer()` begins and waits for the navigation to complete,
+as if the navigation was renderer-initiated, e.g. by setting `window.location`:
+
+```c++
+  // Navigates the main frame.
+  GURL url_1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURLFromRenderer(shell()->GetWebContents(), url_1));
+
+  // Navigates the main frame too.
+  GURL url_2(embedded_test_server()->GetURL("b.com", "/page_with_iframe.html"));
+  EXPECT_TRUE(NavigateToURLFromRenderer(shell()->GetWebContents(), url_2));
+
+  // Navigates the first child frame.
+  GURL url_3(embedded_test_server()->GetURL("a.com", "/empty.html"));
+  EXPECT_TRUE(
+      NavigateToURLFromRenderer(
+          ChildFrameAt(shell()->GetWebContents()->GetMainFrame(), 0),
+          url_3));
+```
+
+## Dynamically generating a page with iframes
+
+> **Note:** using arbitrary hostnames requires the [host resolver to
+> be correctly configured][host-resolver-config].
+
+[`cross_site_iframe_factory.html`][cross-site-iframe-factory] is a helper that
+makes it easy to generate a page with an arbitrary frame tree by navigating to
+a URL. The query string to the URL allows configuration of the frame tree, the
+origin of each frame, and a number of other options:
+
+```c++
+  GURL url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(b(a),c,example.com)"));
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+```
+
+Will generate a page with:
+
+```
+Main frame with origin `a.com`
+  ├─ Child frame #1 with origin `b.com`
+  │    └─ Grandchild frame with origin `a.com`
+  ├─ Child frame #2 with origin `c.com`
+  └─ Child frame #3 with origin `example.com`
+```
+
+## Embedding an `<iframe>` with a specific origin
+
+> **Note:** using arbitrary hostnames requires the [host resolver to
+> be correctly configured][host-resolver-config].
+
+Sometimes, a test page may need to embed a cross-origin URL. This is
+problematic for pages that contain only static HTML, as the embedded test
+server runs on a randomly selected port. Instead, static HTML can use the
+cross-site redirector to generate a cross-origin frame:
+
+```html
+<!-- static_iframe.html -->
+<html>
+  <body>
+    <iframe src="/cross-site/b.com/title1.html">
+  </body>
+</iframe>
+```
+
+**Important**: the cross-site redirector is not enabled by default.
+Override `SetUpOnMainThread()` to configure it like this:
+
+```c++
+  void SetUpOnMainThread() override {
+    ...
+    SetupCrossSiteRedirector(embedded_test_server());
+    ...
+  }
+```
+
+
+## Simulating a slow load
+
+Navigates to a page that takes 60 seconds to load.
+
+```c++
+  GURL url(embedded_test_server()->GetURL("/slow?60");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+```
+
+The embedded test server also registers [other default
+handlers][test-server-default-handlers] that may be useful.
+
+[host-resolver-config]: README.md#Cross_origin-navigations
+[cross-site-iframe-factory]: https://source.chromium.org/chromium/chromium/src/+/master:content/test/data/cross_site_iframe_factory.html
+[test-server-default-handlers]: https://source.chromium.org/chromium/chromium/src/+/master:net/test/embedded_test_server/default_handlers.cc
diff --git a/content/renderer/pepper/pepper_platform_audio_input.cc b/content/renderer/pepper/pepper_platform_audio_input.cc
index 3d1392ce..40a4c1f84 100644
--- a/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -8,7 +8,6 @@
 #include "base/check_op.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/child/child_process.h"
 #include "content/renderer/pepper/pepper_audio_input_host.h"
@@ -90,7 +89,10 @@
 #endif
   DCHECK_GT(shared_memory_region.GetSize(), 0u);
 
-  if (base::ThreadTaskRunnerHandle::Get().get() != main_task_runner_.get()) {
+  // If we're not on the main thread then bounce over to it. Don't use
+  // base::ThreadTaskRunnerHandle::Get() as |main_task_runner_| will never
+  // match that. See crbug.com/1150822.
+  if (!main_task_runner_->BelongsToCurrentThread()) {
     // If shutdown has occurred, |client_| will be NULL and the handles will be
     // cleaned up on the main thread.
     main_task_runner_->PostTask(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 99f25a8d0..859acd0e 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4515,7 +4515,7 @@
   UntrustworthyContextMenuParams params = ContextMenuParamsBuilder::Build(data);
   if (host_context_menu_location.has_value()) {
     // If the context menu request came from the browser, it came with a
-    // position that was stored on blink::WebFrameWidgetBase and is relative to
+    // position that was stored on blink::WebFrameWidgetImpl and is relative to
     // the WindowScreenRect.
     params.x = host_context_menu_location.value().x();
     params.y = host_context_menu_location.value().y();
diff --git a/content/test/data/sxg/generate-test-sxgs.sh b/content/test/data/sxg/generate-test-sxgs.sh
index 3685b89..a802c46 100755
--- a/content/test/data/sxg/generate-test-sxgs.sh
+++ b/content/test/data/sxg/generate-test-sxgs.sh
@@ -13,6 +13,7 @@
     if ! command -v $cmd > /dev/null 2>&1; then
         echo "$cmd is not installed. Please run:"
         echo "  go get -u github.com/WICG/webpackage/go/signedexchange/cmd/..."
+        echo '  export PATH=$PATH:$(go env GOPATH)/bin'
         exit 1
     fi
 done
diff --git a/content/test/data/web_bundle/generate-test-wbns.sh b/content/test/data/web_bundle/generate-test-wbns.sh
index 0734126..22e52a6f 100755
--- a/content/test/data/web_bundle/generate-test-wbns.sh
+++ b/content/test/data/web_bundle/generate-test-wbns.sh
@@ -9,6 +9,7 @@
 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/..."
+    echo '  export PATH=$PATH:$(go env GOPATH)/bin'
     exit 1
 fi
 
diff --git a/content/web_test/renderer/test_runner.cc b/content/web_test/renderer/test_runner.cc
index 75738a92..fbd10909 100644
--- a/content/web_test/renderer/test_runner.cc
+++ b/content/web_test/renderer/test_runner.cc
@@ -3143,7 +3143,7 @@
     if (widget->GetWebWidget()->HasFocus()) {
       auto* view_proxy = frame_proxy->GetWebViewTestProxy();
       // TODO(dtapuska): We should call the exact IPC the browser
-      // calls. ie. WebFrameWidgetBase::SetActive but that isn't
+      // calls. ie. WebFrameWidgetImpl::SetActive but that isn't
       // exposed outside of blink.
       view_proxy->GetWebView()->SetIsActive(false);
       widget->GetWebWidget()->SetFocus(false);
@@ -3158,7 +3158,7 @@
       if (other_widget->GetWebWidget()->HasFocus()) {
         auto* other_view_proxy = other_main_frame->GetWebViewTestProxy();
         // TODO(dtapuska): We should call the exact IPC the browser
-        // calls. ie. WebFrameWidgetBase::SetActive but that isn't
+        // calls. ie. WebFrameWidgetImpl::SetActive but that isn't
         // exposed outside of blink.
         other_view_proxy->GetWebView()->SetIsActive(false);
         other_widget->GetWebWidget()->SetFocus(false);
diff --git a/docs/speed/benchmark/harnesses/tab_search.md b/docs/speed/benchmark/harnesses/tab_search.md
new file mode 100644
index 0000000..8964859
--- /dev/null
+++ b/docs/speed/benchmark/harnesses/tab_search.md
@@ -0,0 +1,73 @@
+# Tab Search Benchmark
+
+## Overview
+
+Tab Search Benchmark is used to measure and monitor Tab Search Web UI performance.
+It captures important metrics such as
+
+* Initial load time
+* Subsequent load time
+* Fetch data time
+* Search user input time
+* Frame time when scrolling
+
+in different stories representing different scenarios
+* tab_search:top10:2020 - Test CUJs with 10 open tabs, after all tabs are loaded
+* tab_search:top50:2020 - Test CUJs with 50 open tabs, after all tabs are loaded
+* tab_search:top100:2020 - Test CUJs with 100 open tabs, after all tabs are loaded
+* tab_search:top10:loading:2020 - Test CUJs with 10 open tabs, before all tabs are loaded
+* tab_search:top50:loading:2020 - Test CUJs with 50 open tabs, before all tabs are loaded
+* tab_search:top100:loading:2020 - Test CUJs with 100 open tabs, before all tabs are loaded
+* tab_search:close_and_open:2020 - Test open, close and reopen Tab Search UI
+
+
+For more information please see this [doc](https://docs.google.com/document/d/1-1ijT7wt05hlBZmSKjX_DaTCzVqpxbfTM1y-j7kYHlc).
+
+## Run the benchmark on pinpoint
+
+In most cases, you only need to run the benchmark on [pinpoint](https://pinpoint-dot-chromeperf.appspot.com/) before/after a CL that may have performance impact. If you don't have platform requirement linux-perf is recommended since they are the most stable trybots for this benchmark.
+
+
+## Run the benchmark locally
+
+In some cases, if trybots cannot meet your requirement or you need to debug on your own machine, use the following command to run the benchmark locally. You need an @google account to be able to do that.
+
+```
+tools/perf/run_benchmark run tab_search --browser-executable=out/Default/chrome --story-filter=tab_search:top10:2020 --pageset-repeat=3
+```
+
+
+## Add new metrics
+
+There are 3 ways to add metrics to the benchmarking code
+
+1. Add UMA metrics to your code and include them in the [benchmark definition](../../../../tools/perf/benchmark/tab_search.py). The listed UMA metrics will show up on the result page automatically.
+2. Add C++ trace with name starts with "webui_metric:". Make sure your trace has category "browser" or add other categories that you use to the benchmark definition. For example:
+   ```c++
+   void Foo::DoWork() {
+     TRACE_EVENT0("browser", "webui_metric:Foo:DoWork");
+     ...
+   }
+   ```
+3. Add Javascript performance.mark() with names end with ":benchmark_begin" and ":benchmark_end". Time between performance.mark('YOUR_METRIC_NAME:benchmark_begin') and performance.mark('YOUR_METRIC_NAME:benchmark') will show up as YOUR_METRIC_NAME on the result page. For example:
+   ```javascript
+   function calc() {
+     performance.mark('calc_time:benchmark_begin');
+     ...
+     performance.mark('calc_time:benchmark_end');
+   }
+   ```
+
+## Record new stories
+
+Add new stories to [here](../../../../tools/perf/page_sets/tab_search/tab_search_stories.py).
+Generally we want to put most of the user journeys in the main story so we only need to run 1 story to verify a CL in most cases. However, if the user journey may affect metrics of other user journeys (e.g. close and reopen Tab Search UI), you should make it a separate story.
+
+Use the following command to record a story
+```
+tools/perf/record_wpr --browser-executable=out/Default/chrome tab_search --story-filter=<YOUR_STORY_NAME>
+```
+and the following command to upload to the cloud.
+```
+upload_to_google_storage.py --bucket chrome-partner-telemetry tools/perf/page_sets/data/tab_search_desktop_<YOUR_RECORDED_HASH>.wprgo
+```
\ No newline at end of file
diff --git a/docs/speed/metrics_changelog/2020_11_cls.md b/docs/speed/metrics_changelog/2020_11_cls.md
new file mode 100644
index 0000000..fa10a66
--- /dev/null
+++ b/docs/speed/metrics_changelog/2020_11_cls.md
@@ -0,0 +1,21 @@
+# Cumulative Layout Shift Changes in Chrome 88
+
+## Changes in Chrome 88
+
+When the `content-visibility: auto` feature was shipped in Chrome 85, a CLS-impacting
+flaw was present: the first time that content is rendered near the screen, a double render
+occurs, once with sizing determined by `contain-intrinsic-size` and the second time
+by the actual size of the content.
+
+If the content was actually on-screen during the double render, it would affect
+CLS scores; therefore the flaw mostly affects above-the-fold
+`content-visibility:auto` content. For such content, there was an unavoidable
+impact on CLS due to the double-render. In Chrome 85, this was a somewhat
+accurate result, because there was a user-visible flicker for
+such above-the-fold content. In Chrome 86, this was
+[fixed](https://chromium-review.googlesource.com/c/chromium/src/+/2348415)
+to avoid a flicker, but the problem with CLS remained.
+
+In Chrome 88, the CLS issue was [fixed](https://chromium-review.googlesource.com/c/chromium/src/+/2556211).
+Going forward, there should be no first-render CLS penalty for
+`content-visibility:auto` content.
diff --git a/docs/speed/metrics_changelog/cls.md b/docs/speed/metrics_changelog/cls.md
index 715946a..e7e95ed 100644
--- a/docs/speed/metrics_changelog/cls.md
+++ b/docs/speed/metrics_changelog/cls.md
@@ -2,6 +2,8 @@
 
 This is a list of changes to [Cumulative Layout Shift](https://web.dev/cls).
 
+* Chrome 88
+  * Metric definition improvement: [no penalty for first unskipped render of content-visibility:auto content](2020_11_cls.md)
 * Chrome 87
   * Metric definition improvement: [Fix problem in Cumulative Layout shift calculation of impact region](2020_10_cls_2.md)
 * Chrome 86
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
index b699bb4..5d80427 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -2507,28 +2507,32 @@
 void AutomationInternalCustomBindings::MaybeSendFocusAndBlur(
     AutomationAXTreeWrapper* tree,
     const ExtensionMsg_AccessibilityEventBundleParams& event_bundle) {
-  // Only send focus or blur if we got one of these events from the originating
-  // renderer. While sending events purely based upon whether the targeted
-  // focus/blur node changed may work, we end up firing too many events since
-  // intermediate states trigger more events than likely necessary. Also, the
-  // |event_from| field is only properly associated with focus/blur when the
-  // event type is also focus/blur.
-  base::Optional<ax::mojom::EventFrom> event_from;
+  ui::AXNode* old_node = nullptr;
+  AutomationAXTreeWrapper* old_wrapper =
+      GetAutomationAXTreeWrapperFromTreeID(focus_tree_id_);
+  if (old_wrapper) {
+    old_node =
+        old_wrapper->GetNodeFromTree(old_wrapper->GetTreeID(), focus_id_);
+  }
+
+  // Determine whether old focus was lost.
+  bool lost_old_focus = old_node == nullptr;
+
+  // Determine whether there's a focus or blur event and take its event from.
+  ax::mojom::EventFrom event_from = ax::mojom::EventFrom::kNone;
+  bool event_bundle_has_focus_or_blur;
   for (const auto& event : event_bundle.events) {
     if (event.event_type == ax::mojom::Event::kBlur ||
-        event.event_type == ax::mojom::Event::kFocus)
+        event.event_type == ax::mojom::Event::kFocus) {
       event_from = event.event_from;
+      event_bundle_has_focus_or_blur = true;
+      break;
+    }
   }
 
-  if (!event_from) {
-    // There was no explicit focus/blur; return early.
-    // Make an exception for the desktop tree, where we can reliably infer
-    // focus/blur even without an explicit event.
-    if (!tree->IsDesktopTree())
-      return;
-
-    event_from = ax::mojom::EventFrom::kNone;
-  }
+  bool is_from_desktop = tree->IsDesktopTree();
+  if (!event_bundle_has_focus_or_blur && !lost_old_focus && !is_from_desktop)
+    return;
 
   // Get the root-most tree.
   AutomationAXTreeWrapper* root_tree = tree;
@@ -2541,13 +2545,6 @@
   if (!GetFocusInternal(root_tree, &new_wrapper, &new_node))
     return;
 
-  ui::AXNode* old_node = nullptr;
-  AutomationAXTreeWrapper* old_wrapper =
-      GetAutomationAXTreeWrapperFromTreeID(focus_tree_id_);
-  if (old_wrapper)
-    old_node =
-        old_wrapper->GetNodeFromTree(old_wrapper->GetTreeID(), focus_id_);
-
   if (new_wrapper == old_wrapper && new_node == old_node)
     return;
 
@@ -2555,7 +2552,7 @@
   if (old_node) {
     ui::AXEvent blur_event;
     blur_event.id = old_node->id();
-    blur_event.event_from = *event_from;
+    blur_event.event_from = event_from;
     blur_event.event_type = ax::mojom::Event::kBlur;
     SendAutomationEvent(old_wrapper->GetTreeID(), event_bundle.mouse_location,
                         blur_event);
@@ -2568,7 +2565,7 @@
   if (new_node) {
     ui::AXEvent focus_event;
     focus_event.id = new_node->id();
-    focus_event.event_from = *event_from;
+    focus_event.event_from = event_from;
     focus_event.event_type = ax::mojom::Event::kFocus;
     SendAutomationEvent(new_wrapper->GetTreeID(), event_bundle.mouse_location,
                         focus_event);
@@ -2737,4 +2734,4 @@
   }
   return sentence_boundary;
 }
-}  // namespace extensions
\ No newline at end of file
+}  // namespace extensions
diff --git a/google_apis/drive/base_requests.cc b/google_apis/drive/base_requests.cc
index 51f2db0..13f6382 100644
--- a/google_apis/drive/base_requests.cc
+++ b/google_apis/drive/base_requests.cc
@@ -980,13 +980,13 @@
 
 DownloadFileRequestBase::DownloadFileRequestBase(
     RequestSender* sender,
-    const DownloadActionCallback& download_action_callback,
+    DownloadActionCallback download_action_callback,
     const GetContentCallback& get_content_callback,
     ProgressCallback progress_callback,
     const GURL& download_url,
     const base::FilePath& output_file_path)
     : UrlFetchRequestBase(sender, ProgressCallback(), progress_callback),
-      download_action_callback_(download_action_callback),
+      download_action_callback_(std::move(download_action_callback)),
       get_content_callback_(get_content_callback),
       download_url_(download_url),
       output_file_path_(output_file_path) {
@@ -1014,13 +1014,13 @@
     const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
-  download_action_callback_.Run(GetErrorCode(), response_file);
+  std::move(download_action_callback_).Run(GetErrorCode(), response_file);
   OnProcessURLFetchResultsComplete();
 }
 
 void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
     DriveApiErrorCode code) {
-  download_action_callback_.Run(code, base::FilePath());
+  std::move(download_action_callback_).Run(code, base::FilePath());
 }
 
 }  // namespace google_apis
diff --git a/google_apis/drive/base_requests.h b/google_apis/drive/base_requests.h
index 14bb3295..3b815e5 100644
--- a/google_apis/drive/base_requests.h
+++ b/google_apis/drive/base_requests.h
@@ -617,8 +617,8 @@
 //============================ DownloadFileRequest ===========================
 
 // Callback type for receiving the completion of DownloadFileRequest.
-typedef base::Callback<void(DriveApiErrorCode error,
-                            const base::FilePath& temp_file)>
+typedef base::OnceCallback<void(DriveApiErrorCode error,
+                                const base::FilePath& temp_file)>
     DownloadActionCallback;
 
 // This is a base class for performing the request for downloading a file.
@@ -641,13 +641,12 @@
   // output_file_path:
   //   Specifies the file path to save the downloaded file.
   //
-  DownloadFileRequestBase(
-      RequestSender* sender,
-      const DownloadActionCallback& download_action_callback,
-      const GetContentCallback& get_content_callback,
-      ProgressCallback progress_callback,
-      const GURL& download_url,
-      const base::FilePath& output_file_path);
+  DownloadFileRequestBase(RequestSender* sender,
+                          DownloadActionCallback download_action_callback,
+                          const GetContentCallback& get_content_callback,
+                          ProgressCallback progress_callback,
+                          const GURL& download_url,
+                          const base::FilePath& output_file_path);
   ~DownloadFileRequestBase() override;
 
  protected:
@@ -662,7 +661,7 @@
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
 
  private:
-  const DownloadActionCallback download_action_callback_;
+  DownloadActionCallback download_action_callback_;
   const GetContentCallback get_content_callback_;
   const GURL download_url_;
   const base::FilePath output_file_path_;
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index b1c118c..4bc95ba3 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -988,12 +988,12 @@
     const DriveApiUrlGenerator& url_generator,
     const std::string& resource_id,
     const base::FilePath& output_file_path,
-    const DownloadActionCallback& download_action_callback,
+    DownloadActionCallback download_action_callback,
     const GetContentCallback& get_content_callback,
     ProgressCallback progress_callback)
     : DownloadFileRequestBase(
           sender,
-          download_action_callback,
+          std::move(download_action_callback),
           get_content_callback,
           progress_callback,
           url_generator.GenerateDownloadFileUrl(resource_id),
diff --git a/google_apis/drive/drive_api_requests.h b/google_apis/drive/drive_api_requests.h
index c595571..5cbf9e67 100644
--- a/google_apis/drive/drive_api_requests.h
+++ b/google_apis/drive/drive_api_requests.h
@@ -1088,7 +1088,7 @@
                       const DriveApiUrlGenerator& url_generator,
                       const std::string& resource_id,
                       const base::FilePath& output_file_path,
-                      const DownloadActionCallback& download_action_callback,
+                      DownloadActionCallback download_action_callback,
                       const GetContentCallback& get_content_callback,
                       ProgressCallback progress_callback);
   ~DownloadFileRequest() override;
diff --git a/google_apis/drive/drive_api_requests_unittest.cc b/google_apis/drive/drive_api_requests_unittest.cc
index 7edcaba..093f09f 100644
--- a/google_apis/drive/drive_api_requests_unittest.cc
+++ b/google_apis/drive/drive_api_requests_unittest.cc
@@ -79,11 +79,11 @@
   TestBatchableDelegate(const GURL url,
                         const std::string& content_type,
                         const std::string& content_data,
-                        const base::Closure& callback)
+                        base::OnceClosure callback)
       : url_(url),
         content_type_(content_type),
         content_data_(content_data),
-        callback_(callback) {}
+        callback_(std::move(callback)) {}
   GURL GetURL() const override { return url_; }
   std::string GetRequestType() const override { return "PUT"; }
   std::vector<std::string> GetExtraRequestHeaders() const override {
@@ -98,11 +98,13 @@
     upload_content->assign(content_data_);
     return true;
   }
-  void NotifyError(DriveApiErrorCode code) override { callback_.Run(); }
+  void NotifyError(DriveApiErrorCode code) override {
+    std::move(callback_).Run();
+  }
   void NotifyResult(DriveApiErrorCode code,
                     const std::string& body,
                     base::OnceClosure closure) override {
-    callback_.Run();
+    std::move(callback_).Run();
     std::move(closure).Run();
   }
   void NotifyUploadProgress(int64_t current, int64_t total) override {
@@ -116,7 +118,7 @@
   GURL url_;
   std::string content_type_;
   std::string content_data_;
-  base::Closure callback_;
+  base::OnceClosure callback_;
   std::vector<int64_t> progress_values_;
 };
 
diff --git a/google_apis/drive/drive_common_callbacks.h b/google_apis/drive/drive_common_callbacks.h
index e8e2f8b..67674a4 100644
--- a/google_apis/drive/drive_common_callbacks.h
+++ b/google_apis/drive/drive_common_callbacks.h
@@ -25,7 +25,8 @@
 // request is already finished, nothing happens.
 typedef base::OnceClosure CancelCallbackOnce;
 typedef base::RepeatingClosure CancelCallbackRepeating;
-// TODO(https://crbug.com/1007686): Remove usage of CancelCallback
+// TODO(https://crbug.com/1007686): Remove usage of CancelCallback.
+// All remaining usages are outside of google_apis/drive.
 typedef base::Closure CancelCallback;
 
 }  // namespace google_apis
diff --git a/google_apis/drive/files_list_request_runner.cc b/google_apis/drive/files_list_request_runner.cc
index 0cbe2a8..47ade28 100644
--- a/google_apis/drive/files_list_request_runner.cc
+++ b/google_apis/drive/files_list_request_runner.cc
@@ -23,14 +23,14 @@
 FilesListRequestRunner::~FilesListRequestRunner() {
 }
 
-CancelCallback FilesListRequestRunner::CreateAndStartWithSizeBackoff(
+CancelCallbackOnce FilesListRequestRunner::CreateAndStartWithSizeBackoff(
     int max_results,
     FilesListCorpora corpora,
     const std::string& team_drive_id,
     const std::string& q,
     const std::string& fields,
     FileListCallback callback) {
-  base::Closure* const cancel_callback = new base::Closure;
+  base::OnceClosure* cancel_callback = new base::OnceClosure;
   std::unique_ptr<drive::FilesListRequest> request =
       std::make_unique<drive::FilesListRequest>(
           request_sender_, url_generator_,
@@ -46,15 +46,15 @@
 
   // The cancellation callback is owned by the completion callback, so it must
   // not be used after |callback| is called.
-  return base::Bind(&FilesListRequestRunner::OnCancel,
-                    weak_ptr_factory_.GetWeakPtr(),
-                    base::Unretained(cancel_callback));
+  return base::BindOnce(&FilesListRequestRunner::OnCancel,
+                        weak_ptr_factory_.GetWeakPtr(),
+                        base::Unretained(cancel_callback));
 }
 
-void FilesListRequestRunner::OnCancel(base::Closure* cancel_callback) {
+void FilesListRequestRunner::OnCancel(CancelCallbackOnce* cancel_callback) {
   DCHECK(cancel_callback);
   DCHECK(!cancel_callback->is_null());
-  cancel_callback->Run();
+  std::move(*cancel_callback).Run();
 }
 
 void FilesListRequestRunner::OnCompleted(int max_results,
@@ -63,11 +63,11 @@
                                          const std::string& q,
                                          const std::string& fields,
                                          FileListCallback callback,
-                                         CancelCallback* cancel_callback,
+                                         CancelCallbackOnce* cancel_callback,
                                          DriveApiErrorCode error,
                                          std::unique_ptr<FileList> entry) {
   if (!request_completed_callback_for_testing_.is_null())
-    request_completed_callback_for_testing_.Run();
+    std::move(request_completed_callback_for_testing_).Run();
 
   if (error == google_apis::DRIVE_RESPONSE_TOO_LARGE && max_results > 1) {
     CreateAndStartWithSizeBackoff(max_results / 2, corpora, team_drive_id, q,
@@ -79,8 +79,8 @@
 }
 
 void FilesListRequestRunner::SetRequestCompletedCallbackForTesting(
-    const base::Closure& callback) {
-  request_completed_callback_for_testing_ = callback;
+    base::OnceClosure callback) {
+  request_completed_callback_for_testing_ = std::move(callback);
 }
 
 }  // namespace google_apis
diff --git a/google_apis/drive/files_list_request_runner.h b/google_apis/drive/files_list_request_runner.h
index 6b01004..21af4ba 100644
--- a/google_apis/drive/files_list_request_runner.h
+++ b/google_apis/drive/files_list_request_runner.h
@@ -29,22 +29,23 @@
 
   // Creates a FilesListRequest instance and starts the request with a backoff
   // retry in case of DRIVE_RESPONSE_TOO_LARGE error code.
-  CancelCallback CreateAndStartWithSizeBackoff(int max_results,
-                                               FilesListCorpora corpora,
-                                               const std::string& team_drive_id,
-                                               const std::string& q,
-                                               const std::string& fields,
-                                               FileListCallback callback);
+  CancelCallbackOnce CreateAndStartWithSizeBackoff(
+      int max_results,
+      FilesListCorpora corpora,
+      const std::string& team_drive_id,
+      const std::string& q,
+      const std::string& fields,
+      FileListCallback callback);
 
   ~FilesListRequestRunner();
 
-  void SetRequestCompletedCallbackForTesting(const base::Closure& callback);
+  void SetRequestCompletedCallbackForTesting(base::OnceClosure callback);
 
  private:
   // Called when the cancelling callback returned by
   // CreateAndStartWithSizeBackoff is invoked. Once called cancels the current
   // request.
-  void OnCancel(CancelCallback* cancel_callback);
+  void OnCancel(CancelCallbackOnce* cancel_callback);
 
   // Called when a single request is completed with either a success or an
   // error. In case of DRIVE_RESPONSE_TOO_LARGE it will retry the request with
@@ -55,13 +56,13 @@
                    const std::string& q,
                    const std::string& fields,
                    FileListCallback callback,
-                   CancelCallback* cancel_callback,
+                   CancelCallbackOnce* cancel_callback,
                    DriveApiErrorCode error,
                    std::unique_ptr<FileList> entry);
 
   RequestSender* request_sender_;                          // Not owned.
   const google_apis::DriveApiUrlGenerator url_generator_;  // Not owned.
-  base::Closure request_completed_callback_for_testing_;
+  base::OnceClosure request_completed_callback_for_testing_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/google_apis/drive/files_list_request_runner_unittest.cc b/google_apis/drive/files_list_request_runner_unittest.cc
index a1c693d..b09f7914 100644
--- a/google_apis/drive/files_list_request_runner_unittest.cc
+++ b/google_apis/drive/files_list_request_runner_unittest.cc
@@ -122,7 +122,7 @@
   }
 
   void TearDown() override {
-    on_completed_callback_ = base::Closure();
+    on_completed_callback_ = base::OnceClosure();
     http_request_.reset();
     response_error_.reset();
     response_entry_.reset();
@@ -133,7 +133,7 @@
   void OnCompleted(DriveApiErrorCode error, std::unique_ptr<FileList> entry) {
     response_error_.reset(new DriveApiErrorCode(error));
     response_entry_ = std::move(entry);
-    on_completed_callback_.Run();
+    std::move(on_completed_callback_).Run();
   }
 
  protected:
@@ -166,7 +166,7 @@
   mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_;
   scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
       test_shared_loader_factory_;
-  base::Closure on_completed_callback_;
+  base::OnceClosure on_completed_callback_;
 
   // Response set by test cases to be returned from the HTTP server.
   std::unique_ptr<net::test_server::BasicHttpResponse> fake_server_response_;
diff --git a/google_apis/drive/request_sender_unittest.cc b/google_apis/drive/request_sender_unittest.cc
index c414c83..387c1b93 100644
--- a/google_apis/drive/request_sender_unittest.cc
+++ b/google_apis/drive/request_sender_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "google_apis/drive/base_requests.h"
+#include "google_apis/drive/drive_common_callbacks.h"
 #include "google_apis/drive/dummy_auth_service.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -146,7 +147,7 @@
   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr =
       request_ptr->GetWeakPtr();
 
-  base::Closure cancel_closure =
+  CancelCallbackOnce cancel_closure =
       request_sender_.StartRequestWithAuthRetry(std::move(request));
   EXPECT_TRUE(!cancel_closure.is_null());
 
@@ -158,7 +159,7 @@
 
   // It is safe to run the cancel closure even after the request is finished.
   // It is just no-op. The TestRequest::Cancel method is not called.
-  cancel_closure.Run();
+  std::move(cancel_closure).Run();
   EXPECT_EQ(SUCCESS, finish_reason);
 }
 
@@ -169,12 +170,12 @@
       &request_sender_, &start_called, &finish_reason);
   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
 
-  base::Closure cancel_closure =
+  CancelCallbackOnce cancel_closure =
       request_sender_.StartRequestWithAuthRetry(std::move(request));
   EXPECT_TRUE(!cancel_closure.is_null());
   EXPECT_TRUE(start_called);
 
-  cancel_closure.Run();
+  std::move(cancel_closure).Run();
   EXPECT_EQ(CANCEL, finish_reason);
   EXPECT_FALSE(weak_ptr);  // The request object is deleted.
 }
@@ -189,7 +190,7 @@
       &request_sender_, &start_called, &finish_reason);
   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
 
-  base::Closure cancel_closure =
+  CancelCallbackOnce cancel_closure =
       request_sender_.StartRequestWithAuthRetry(std::move(request));
   EXPECT_TRUE(!cancel_closure.is_null());
 
@@ -210,7 +211,7 @@
   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr =
       request_ptr->GetWeakPtr();
 
-  base::Closure cancel_closure =
+  CancelCallbackOnce cancel_closure =
       request_sender_.StartRequestWithAuthRetry(std::move(request));
   EXPECT_TRUE(!cancel_closure.is_null());
 
@@ -232,7 +233,7 @@
   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr =
       request_ptr->GetWeakPtr();
 
-  base::Closure cancel_closure =
+  CancelCallbackOnce cancel_closure =
       request_sender_.StartRequestWithAuthRetry(std::move(request));
   EXPECT_TRUE(!cancel_closure.is_null());
 
diff --git a/google_apis/drive/test_util.h b/google_apis/drive/test_util.h
index 01174f6..ee767ce6 100644
--- a/google_apis/drive/test_util.h
+++ b/google_apis/drive/test_util.h
@@ -43,10 +43,11 @@
 void RunAndQuit(base::RunLoop* run_loop, base::OnceClosure closure);
 
 // Returns callback which runs the given |callback| and then quits |run_loop|.
-template<typename CallbackType>
+template <typename CallbackType>
 CallbackType CreateQuitCallback(base::RunLoop* run_loop,
-                                const CallbackType& callback) {
-  return CreateComposedCallback(base::Bind(&RunAndQuit, run_loop), callback);
+                                CallbackType callback) {
+  return CreateComposedCallback(base::BindOnce(&RunAndQuit, run_loop),
+                                std::move(callback));
 }
 
 // Removes |prefix| from |input| and stores the result in |output|. Returns
@@ -234,35 +235,39 @@
 
 }  // namespace internal
 
-template<typename T1>
-base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType)>
+template <typename T1>
+base::OnceCallback<
+    void(typename internal::CopyResultCallbackHelper<T1>::InType)>
 CreateCopyResultCallback(T1* out1) {
-  return base::Bind(&internal::CopyResultCallback<T1>, out1);
+  return base::BindOnce(&internal::CopyResultCallback<T1>, out1);
 }
 
-template<typename T1, typename T2>
-base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
-                    typename internal::CopyResultCallbackHelper<T2>::InType)>
+template <typename T1, typename T2>
+base::OnceCallback<
+    void(typename internal::CopyResultCallbackHelper<T1>::InType,
+         typename internal::CopyResultCallbackHelper<T2>::InType)>
 CreateCopyResultCallback(T1* out1, T2* out2) {
-  return base::Bind(&internal::CopyResultCallback<T1, T2>, out1, out2);
+  return base::BindOnce(&internal::CopyResultCallback<T1, T2>, out1, out2);
 }
 
-template<typename T1, typename T2, typename T3>
-base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
-                    typename internal::CopyResultCallbackHelper<T2>::InType,
-                    typename internal::CopyResultCallbackHelper<T3>::InType)>
+template <typename T1, typename T2, typename T3>
+base::OnceCallback<
+    void(typename internal::CopyResultCallbackHelper<T1>::InType,
+         typename internal::CopyResultCallbackHelper<T2>::InType,
+         typename internal::CopyResultCallbackHelper<T3>::InType)>
 CreateCopyResultCallback(T1* out1, T2* out2, T3* out3) {
-  return base::Bind(
-      &internal::CopyResultCallback<T1, T2, T3>, out1, out2, out3);
+  return base::BindOnce(&internal::CopyResultCallback<T1, T2, T3>, out1, out2,
+                        out3);
 }
 
-template<typename T1, typename T2, typename T3, typename T4>
-base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
-                    typename internal::CopyResultCallbackHelper<T2>::InType,
-                    typename internal::CopyResultCallbackHelper<T3>::InType,
-                    typename internal::CopyResultCallbackHelper<T4>::InType)>
+template <typename T1, typename T2, typename T3, typename T4>
+base::OnceCallback<
+    void(typename internal::CopyResultCallbackHelper<T1>::InType,
+         typename internal::CopyResultCallbackHelper<T2>::InType,
+         typename internal::CopyResultCallbackHelper<T3>::InType,
+         typename internal::CopyResultCallbackHelper<T4>::InType)>
 CreateCopyResultCallback(T1* out1, T2* out2, T3* out3, T4* out4) {
-  return base::Bind(
+  return base::BindOnce(
       &internal::CopyResultCallback<T1, T2, T3, T4>,
       internal::OutputParams<T1, T2, T3, T4>(out1, out2, out3, out4));
 }
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index c72b2bc..b3c77b9cd 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -17,6 +17,7 @@
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/skia_utils.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
+#include "gpu/config/gpu_finch_features.h"
 #include "gpu/config/skia_limits.h"
 #include "gpu/vulkan/buildflags.h"
 #include "skia/buildflags.h"
@@ -33,10 +34,6 @@
 #include "gpu/vulkan/vulkan_device_queue.h"
 #endif
 
-#if defined(OS_ANDROID)
-#include "gpu/config/gpu_finch_features.h"
-#endif
-
 #if defined(OS_FUCHSIA)
 #include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
 #endif
@@ -178,12 +175,10 @@
     case GrContextType::kVulkan:
       if (vk_context_provider_) {
 #if BUILDFLAG(ENABLE_VULKAN)
-        gr_context_ = vk_context_provider_->GetGrContext();
         external_semaphore_pool_ =
             std::make_unique<ExternalSemaphorePool>(this);
 #endif
         use_virtualized_gl_contexts_ = false;
-        DCHECK(gr_context_);
       }
       break;
     case GrContextType::kMetal:
@@ -271,6 +266,16 @@
   DetermineGrCacheLimitsFromAvailableMemory(&max_resource_cache_bytes,
                                             &glyph_cache_max_texture_bytes);
 
+  // If you make any changes to the GrContext::Options here that could
+  // affect text rendering, make sure to match the capabilities initialized
+  // in GetCapabilities and ensuring these are also used by the
+  // PaintOpBufferSerializer.
+  GrContextOptions options = GetDefaultGrContextOptions(gr_context_type_);
+  options.fPersistentCache = cache;
+  options.fShaderErrorHandler = this;
+  if (gpu_preferences.force_max_texture_size)
+    options.fMaxTextureSizeOverride = gpu_preferences.force_max_texture_size;
+
   if (gr_context_type_ == GrContextType::kGL) {
     DCHECK(context_->IsCurrent(nullptr));
     bool use_version_es2 = false;
@@ -296,25 +301,32 @@
             glProgramBinary(program, binaryFormat, binary, length);
           };
     }
-    // If you make any changes to the GrContext::Options here that could
-    // affect text rendering, make sure to match the capabilities initialized
-    // in GetCapabilities and ensuring these are also used by the
-    // PaintOpBufferSerializer.
-    GrContextOptions options = GetDefaultGrContextOptions(GrContextType::kGL);
     options.fDriverBugWorkarounds =
         GrDriverBugWorkarounds(workarounds.ToIntSet());
-    options.fPersistentCache = cache;
     options.fAvoidStencilBuffers = workarounds.avoid_stencil_buffers;
     if (workarounds.disable_program_disk_cache) {
       options.fShaderCacheStrategy =
           GrContextOptions::ShaderCacheStrategy::kBackendSource;
     }
-    options.fShaderErrorHandler = this;
-    if (gpu_preferences.force_max_texture_size)
-      options.fMaxTextureSizeOverride = gpu_preferences.force_max_texture_size;
     options.fPreferExternalImagesOverES3 = true;
     owned_gr_context_ = GrDirectContext::MakeGL(std::move(interface), options);
     gr_context_ = owned_gr_context_.get();
+  } else if (gr_context_type_ == GrContextType::kVulkan) {
+#if BUILDFLAG(ENABLE_VULKAN)
+    if (vk_context_provider_) {
+      // TODO(vasilyt): Remove this if there is no problem with caching.
+      if (!base::FeatureList::IsEnabled(
+              features::kEnableGrShaderCacheForVulkan))
+        options.fPersistentCache = nullptr;
+
+      if (!vk_context_provider_->InitializeGrContext(options)) {
+        LOG(ERROR) << "Failed to initialize GrContext for Vulkan.";
+        return false;
+      }
+      gr_context_ = vk_context_provider_->GetGrContext();
+      DCHECK(gr_context_);
+    }
+#endif
   }
 
   if (!gr_context_) {
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index b108ba9..2a6674d7 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -123,6 +123,10 @@
 const base::Feature kEnableSharedImageForWebview{
     "EnableSharedImageForWebview", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enable GrShaderCache to use with Vulkan backend.
+const base::Feature kEnableGrShaderCacheForVulkan{
+    "EnableGrShaderCacheForVulkan", base::FEATURE_ENABLED_BY_DEFAULT};
+
 bool IsUsingVulkan() {
   bool enable = base::FeatureList::IsEnabled(kVulkan);
 #if defined(OS_ANDROID)
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index 055c174..eb322d2a 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -53,6 +53,8 @@
 
 GPU_EXPORT extern const base::Feature kEnableSharedImageForWebview;
 
+GPU_EXPORT extern const base::Feature kEnableGrShaderCacheForVulkan;
+
 GPU_EXPORT bool IsUsingVulkan();
 #if defined(OS_ANDROID)
 GPU_EXPORT bool IsAImageReaderEnabled();
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index be75742a..fba7cdf 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -19045,7 +19045,7 @@
         cmd: "recipes"
       }
       properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
-      execution_timeout_secs: 21600
+      execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
@@ -20849,7 +20849,7 @@
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builderless:1"
       dimensions: "cores:8"
-      dimensions: "cpu:x86"
+      dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.ci"
       dimensions: "ssd:0"
@@ -20896,7 +20896,7 @@
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builderless:1"
       dimensions: "cores:8"
-      dimensions: "cpu:x86"
+      dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.ci"
       dimensions: "ssd:0"
@@ -21357,6 +21357,194 @@
       }
     }
     builders {
+      name: "win32-updater-builder-dbg"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows-10"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
+      name: "win32-updater-builder-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:Windows-10"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
+      name: "win7(32)-updater-tester-dbg"
+      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: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
+      name: "win7(32)-updater-tester-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: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
       name: "win7-updater-tester-dbg"
       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 d12720bb..1aed1ab5 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -9354,18 +9354,28 @@
     short_name: "bld"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/win7(32)-updater-tester-dbg"
+    category: "debug|win (32)"
+    short_name: "7"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/win32-updater-builder-dbg"
+    category: "debug|win (32)"
+    short_name: "bld"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/win10-updater-tester-dbg"
-    category: "debug|win"
+    category: "debug|win (64)"
     short_name: "10"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/win7-updater-tester-dbg"
-    category: "debug|win"
+    category: "debug|win (64)"
     short_name: "7"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/win-updater-builder-dbg"
-    category: "debug|win"
+    category: "debug|win (64)"
     short_name: "bld"
   }
   builders {
@@ -9409,18 +9419,28 @@
     short_name: "bld"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/win7(32)-updater-tester-rel"
+    category: "release|win (32)"
+    short_name: "7"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/win32-updater-builder-rel"
+    category: "release|win (32)"
+    short_name: "bld"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/win10-updater-tester-rel"
-    category: "release|win"
+    category: "release|win (64)"
     short_name: "10"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/win7-updater-tester-rel"
-    category: "release|win"
+    category: "release|win (64)"
     short_name: "7"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/win-updater-builder-rel"
-    category: "release|win"
+    category: "release|win (64)"
     short_name: "bld"
   }
   header {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 40d4a9e..db73ef4 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -6321,6 +6321,54 @@
   }
 }
 job {
+  id: "win32-updater-builder-dbg"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "win32-updater-builder-dbg"
+  }
+}
+job {
+  id: "win32-updater-builder-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "win32-updater-builder-rel"
+  }
+}
+job {
+  id: "win7(32)-updater-tester-dbg"
+  realm: "ci"
+  acls {
+    role: TRIGGERER
+    granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "win7(32)-updater-tester-dbg"
+  }
+}
+job {
+  id: "win7(32)-updater-tester-rel"
+  realm: "ci"
+  acls {
+    role: TRIGGERER
+    granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "win7(32)-updater-tester-rel"
+  }
+}
+job {
   id: "win7-updater-tester-dbg"
   realm: "ci"
   acls {
@@ -6655,6 +6703,8 @@
   triggers: "win32-archive-rel"
   triggers: "win32-arm64-rel"
   triggers: "win32-official"
+  triggers: "win32-updater-builder-dbg"
+  triggers: "win32-updater-builder-rel"
   triggers: "Chromium Android ARM 32-bit Goma RBE Staging"
   triggers: "Chromium Android ARM 32-bit Goma RBE ToT"
   triggers: "Chromium Android ARM 32-bit Goma RBE ToT (ATS)"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 95b576b2..a5aa22a 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -2730,47 +2730,83 @@
 ci.updater_builder(
     name = "win-updater-builder-dbg",
     console_view_entry = ci.console_view_entry(
-        category = "debug|win",
+        category = "debug|win (64)",
         short_name = "bld",
     ),
     os = os.WINDOWS_DEFAULT,
-    cpu = cpu.X86,
+    builderless = True,
+)
+
+ci.updater_builder(
+    name = "win32-updater-builder-dbg",
+    console_view_entry = ci.console_view_entry(
+        category = "debug|win (32)",
+        short_name = "bld",
+    ),
+    os = os.WINDOWS_DEFAULT,
     builderless = True,
 )
 
 ci.updater_builder(
     name = "win-updater-builder-rel",
     console_view_entry = ci.console_view_entry(
-        category = "release|win",
+        category = "release|win (64)",
         short_name = "bld",
     ),
     os = os.WINDOWS_DEFAULT,
-    cpu = cpu.X86,
+    builderless = True,
+)
+
+ci.updater_builder(
+    name = "win32-updater-builder-rel",
+    console_view_entry = ci.console_view_entry(
+        category = "release|win (32)",
+        short_name = "bld",
+    ),
+    os = os.WINDOWS_DEFAULT,
     builderless = True,
 )
 
 ci.updater_builder(
     name = "win7-updater-tester-dbg",
     console_view_entry = ci.console_view_entry(
-        category = "debug|win",
+        category = "debug|win (64)",
         short_name = "7",
     ),
     triggered_by = ["win-updater-builder-dbg"],
 )
 
 ci.updater_builder(
+    name = "win7(32)-updater-tester-dbg",
+    console_view_entry = ci.console_view_entry(
+        category = "debug|win (32)",
+        short_name = "7",
+    ),
+    triggered_by = ["win32-updater-builder-dbg"],
+)
+
+ci.updater_builder(
     name = "win7-updater-tester-rel",
     console_view_entry = ci.console_view_entry(
-        category = "release|win",
+        category = "release|win (64)",
         short_name = "7",
     ),
     triggered_by = ["win-updater-builder-rel"],
 )
 
 ci.updater_builder(
+    name = "win7(32)-updater-tester-rel",
+    console_view_entry = ci.console_view_entry(
+        category = "release|win (32)",
+        short_name = "7",
+    ),
+    triggered_by = ["win32-updater-builder-rel"],
+)
+
+ci.updater_builder(
     name = "win10-updater-tester-dbg",
     console_view_entry = ci.console_view_entry(
-        category = "debug|win",
+        category = "debug|win (64)",
         short_name = "10",
     ),
     triggered_by = ["win-updater-builder-dbg"],
@@ -2779,7 +2815,7 @@
 ci.updater_builder(
     name = "win10-updater-tester-rel",
     console_view_entry = ci.console_view_entry(
-        category = "release|win",
+        category = "release|win (64)",
         short_name = "10",
     ),
     triggered_by = ["win-updater-builder-rel"],
@@ -4463,9 +4499,6 @@
         category = "mac",
         short_name = "a64",
     ),
-    # TODO(gbeaty) Once we have sufficient test capacity to not need to
-    # serialize tests, use the default execution_timout
-    execution_timeout = 6 * time.hour,
     tree_closing = False,
     triggered_by = [builder_name("mac-arm64-rel")],
 )
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
index ad5ad907..8a126c86e 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
@@ -19,7 +19,6 @@
 #include "components/prefs/pref_member.h"
 #include "ios/chrome/browser/ios_chrome_io_thread.h"
 #include "ios/chrome/browser/net/net_types.h"
-#include "net/cert/ct_verifier.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_network_session.h"
@@ -243,7 +242,6 @@
       proxy_resolution_service_;
   mutable std::unique_ptr<net::TransportSecurityState>
       transport_security_state_;
-  mutable std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
   mutable std::unique_ptr<net::HttpServerProperties> http_server_properties_;
   mutable std::unique_ptr<net::TransportSecurityPersister>
       transport_security_persister_;
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
index 58d2b440..2098f86 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -47,7 +47,6 @@
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
 #include "net/cert/cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_transaction_factory.h"
@@ -356,8 +355,6 @@
       io_thread_globals->cert_verifier.get());
   main_request_context_->set_ct_policy_enforcer(
       io_thread_globals->ct_policy_enforcer.get());
-  main_request_context_->set_cert_transparency_verifier(
-      io_thread_globals->cert_transparency_verifier.get());
   main_request_context_->set_quic_context(
       io_thread_globals->quic_context.get());
 
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index 1e7bb02e0..e4e4f8b0 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -165,9 +165,6 @@
       io_thread_globals->http_auth_handler_factory.get());
   main_context->set_proxy_resolution_service(proxy_resolution_service());
 
-  main_context->set_cert_transparency_verifier(
-      io_thread_globals->cert_transparency_verifier.get());
-
   // For incognito, we use the default non-persistent HttpServerProperties.
   set_http_server_properties(std::make_unique<net::HttpServerProperties>());
   main_context->set_http_server_properties(http_server_properties());
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
index 2f15238..33557a9 100644
--- a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
+++ b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
@@ -126,7 +126,9 @@
 
 // Tests that the open in bar is correctly displayed when a compatible URL is
 // loaded and tapping on the web view makes it appear or disappear.
-- (void)testOpenInDisplay {
+//
+// Disabled due to flakiness: http://crbug.com/1146303
+- (void)DISABLED_testOpenInDisplay {
   // Check that the open in bar is correctly displayed when a compatible URL is
   // loaded.
   [ChromeEarlGrey loadURL:self.testServer->GetURL(kPDFPath)];
diff --git a/ios/components/io_thread/ios_io_thread.h b/ios/components/io_thread/ios_io_thread.h
index e8097ac..9149393 100644
--- a/ios/components/io_thread/ios_io_thread.h
+++ b/ios/components/io_thread/ios_io_thread.h
@@ -30,7 +30,6 @@
 class CTPolicyEnforcer;
 class CertVerifier;
 class CookieStore;
-class CTVerifier;
 class HostResolver;
 class HttpAuthHandlerFactory;
 class HttpAuthPreferences;
@@ -102,7 +101,6 @@
     // used to enforce pinning for system requests and will only use built-in
     // pins.
     std::unique_ptr<net::TransportSecurityState> transport_security_state;
-    std::unique_ptr<net::CTVerifier> cert_transparency_verifier;
     std::unique_ptr<net::SSLConfigService> ssl_config_service;
     std::unique_ptr<net::HttpAuthPreferences> http_auth_preferences;
     std::unique_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory;
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm
index f390afbf..28ec8c7 100644
--- a/ios/components/io_thread/ios_io_thread.mm
+++ b/ios/components/io_thread/ios_io_thread.mm
@@ -40,8 +40,6 @@
 #include "net/base/logging_network_change_observer.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/cert/multi_threaded_cert_verifier.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/cookies/cookie_store.h"
@@ -247,7 +245,6 @@
 
   globals_->transport_security_state.reset(new net::TransportSecurityState());
 
-  globals_->cert_transparency_verifier.reset(new net::MultiLogCTVerifier());
   globals_->ct_policy_enforcer.reset(new net::DefaultCTPolicyEnforcer());
 
   globals_->ssl_config_service.reset(new net::SSLConfigServiceDefaults());
@@ -352,8 +349,6 @@
   context->set_cert_verifier(globals->cert_verifier.get());
   context->set_transport_security_state(
       globals->transport_security_state.get());
-  context->set_cert_transparency_verifier(
-      globals->cert_transparency_verifier.get());
   context->set_ssl_config_service(globals->ssl_config_service.get());
   context->set_http_auth_handler_factory(
       globals->http_auth_handler_factory.get());
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index 8973e38..7a811f0 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -21,7 +21,6 @@
 #include "net/base/network_delegate_impl.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/dns/host_resolver.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_cache.h"
@@ -91,8 +90,6 @@
 
     storage_->set_transport_security_state(
         std::make_unique<net::TransportSecurityState>());
-    storage_->set_cert_transparency_verifier(
-        base::WrapUnique(new net::MultiLogCTVerifier));
     storage_->set_ct_policy_enforcer(
         base::WrapUnique(new net::DefaultCTPolicyEnforcer));
     storage_->set_quic_context(std::make_unique<net::QuicContext>());
@@ -116,8 +113,6 @@
         url_request_context_->cert_verifier();
     network_session_context.transport_security_state =
         url_request_context_->transport_security_state();
-    network_session_context.cert_transparency_verifier =
-        url_request_context_->cert_transparency_verifier();
     network_session_context.ct_policy_enforcer =
         url_request_context_->ct_policy_enforcer();
     network_session_context.net_log = url_request_context_->net_log();
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index c3ba941..2f79e2bb 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -22,7 +22,6 @@
 #include "net/base/network_delegate_impl.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/dns/host_resolver.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_cache.h"
@@ -104,8 +103,6 @@
 
     storage_->set_transport_security_state(
         std::make_unique<net::TransportSecurityState>());
-    storage_->set_cert_transparency_verifier(
-        base::WrapUnique(new net::MultiLogCTVerifier));
     storage_->set_ct_policy_enforcer(
         base::WrapUnique(new net::DefaultCTPolicyEnforcer));
     storage_->set_quic_context(std::make_unique<net::QuicContext>());
@@ -130,8 +127,6 @@
         url_request_context_->cert_verifier();
     network_session_context.transport_security_state =
         url_request_context_->transport_security_state();
-    network_session_context.cert_transparency_verifier =
-        url_request_context_->cert_transparency_verifier();
     network_session_context.net_log = url_request_context_->net_log();
     network_session_context.proxy_resolution_service =
         url_request_context_->proxy_resolution_service();
diff --git a/media/capture/video/chromeos/stream_buffer_manager.cc b/media/capture/video/chromeos/stream_buffer_manager.cc
index 75bd224..611d054 100644
--- a/media/capture/video/chromeos/stream_buffer_manager.cc
+++ b/media/capture/video/chromeos/stream_buffer_manager.cc
@@ -452,8 +452,9 @@
       stream_context->buffer_dimension, *gfx_format,
       stream_context->buffer_usage, base::NullCallback());
   stream_context->free_buffers.push(vcd_buffer.id);
-  stream_context->buffers.insert(std::make_pair(
-      vcd_buffer.id, BufferPair(std::move(gmb), std::move(vcd_buffer))));
+  const int id = vcd_buffer.id;
+  stream_context->buffers.insert(
+      std::make_pair(id, BufferPair(std::move(gmb), std::move(vcd_buffer))));
 }
 
 void StreamBufferManager::DestroyCurrentStreamsAndBuffers() {
diff --git a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
index 7d171ad..073135c 100644
--- a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
+++ b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
@@ -192,13 +192,14 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitSlice");
   bool uses_crypto = false;
-  VAEncryptionParameters crypto_params;
-  if (!subsamples.empty() && subsamples[0].cypher_bytes) {
+  VAEncryptionParameters crypto_params = {};
+  if ((!subsamples.empty() && subsamples[0].cypher_bytes) ||
+      IsProtectedSession()) {
     // If there is only one clear byte, then this is CENC v1, full sample
     // encryption (i.e. only the NALU header is unencrypted).
-    ProtectedSessionState state =
-        SetupDecryptDecode(subsamples[0].clear_bytes == 1, &crypto_params,
-                           &encryption_segment_info_, subsamples);
+    ProtectedSessionState state = SetupDecryptDecode(
+        !subsamples.empty() && subsamples[0].clear_bytes == 1, size,
+        &crypto_params, &encryption_segment_info_, subsamples);
     if (state == ProtectedSessionState::kFailed) {
       LOG(ERROR) << "SubmitSlice fails because we couldn't setup the protected "
                     "session";
diff --git a/media/gpu/vaapi/vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
index 565ac34..2b0b157 100644
--- a/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
+++ b/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
@@ -75,6 +75,7 @@
 VaapiVideoDecoderDelegate::ProtectedSessionState
 VaapiVideoDecoderDelegate::SetupDecryptDecode(
     bool full_sample,
+    size_t size,
     VAEncryptionParameters* crypto_params,
     std::vector<VAEncryptionSegmentInfo>* segments,
     const std::vector<SubsampleEntry>& subsamples) {
@@ -105,6 +106,25 @@
   }
 
   DCHECK_EQ(protected_session_state_, ProtectedSessionState::kCreated);
+
+  if (decrypt_config_->encryption_scheme() == EncryptionScheme::kCenc) {
+    crypto_params->encryption_type =
+        full_sample_ ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128;
+  } else {
+    crypto_params->encryption_type = VA_ENCRYPTION_TYPE_CBC;
+  }
+
+  if (subsamples.empty()) {
+    // We still need to specify the crypto params to the driver for some reason
+    // and indicate the entire content is clear.
+    VAEncryptionSegmentInfo segment_info = {};
+    segment_info.segment_length = segment_info.init_byte_length = size;
+    segments->emplace_back(std::move(segment_info));
+    crypto_params->num_segments = 1;
+    crypto_params->segment_info = &segments->back();
+    return protected_session_state_;
+  }
+
   if (full_sample_ != full_sample) {
     LOG(ERROR) << "Cannot switch between full/subsample mid session";
     protected_session_state_ = ProtectedSessionState::kFailed;
@@ -124,14 +144,6 @@
     return ProtectedSessionState::kInProcess;
   }
 
-  memset(crypto_params, 0, sizeof(*crypto_params));
-  if (decrypt_config_->encryption_scheme() == EncryptionScheme::kCenc) {
-    crypto_params->encryption_type =
-        full_sample_ ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128;
-  } else {
-    crypto_params->encryption_type = VA_ENCRYPTION_TYPE_CBC;
-  }
-
   crypto_params->num_segments = subsamples.size();
   // For multi-slice, we may already have segment info in the vector.
   const size_t segment_vec_offset = segments->size();
diff --git a/media/gpu/vaapi/vaapi_video_decoder_delegate.h b/media/gpu/vaapi/vaapi_video_decoder_delegate.h
index 664c37a..345a258 100644
--- a/media/gpu/vaapi/vaapi_video_decoder_delegate.h
+++ b/media/gpu/vaapi/vaapi_video_decoder_delegate.h
@@ -78,13 +78,23 @@
   // encryption or not and must remain consistent for a session. If everything
   // is setup for a protected session, it will fill in the |crypto_params|.
   // |segments| must retain its memory until the frame is submitted.
-  // |subsamples| is for the current slice.
-  VaapiVideoDecoderDelegate::ProtectedSessionState SetupDecryptDecode(
+  // |subsamples| is for the current slice. |size| is the size of the slice
+  // data. This should be called if IsProtectedSession() is true even if the
+  // data is not encrypted (i.e. |subsamples| is empty), and in that case the
+  // |full_sample| parameter is ignored.
+  ProtectedSessionState SetupDecryptDecode(
       bool full_sample,
+      size_t size,
       VAEncryptionParameters* crypto_params,
       std::vector<VAEncryptionSegmentInfo>* segments,
       const std::vector<SubsampleEntry>& subsamples);
 
+  // Returns true if we have established a protected session, in which case
+  // SetupDecryptDecode() should be called for every slice after that.
+  bool IsProtectedSession() const {
+    return protected_session_state_ == ProtectedSessionState::kCreated;
+  }
+
   // Both owned by caller.
   DecodeSurfaceHandler<VASurface>* const vaapi_dec_;
   scoped_refptr<VaapiWrapper> vaapi_wrapper_;
diff --git a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc
index a20e9f4..0da2be8 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc
+++ b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc
@@ -89,8 +89,8 @@
     if (!decrypt_config->subsamples().empty() &&
         decrypt_config->subsamples()[0].cypher_bytes) {
       ProtectedSessionState state = SetupDecryptDecode(
-          false /* full_sample */, &crypto_param, &encryption_segment_info,
-          decrypt_config->subsamples());
+          false /* full_sample */, frame_hdr->frame_size, &crypto_param,
+          &encryption_segment_info, decrypt_config->subsamples());
       if (state == ProtectedSessionState::kFailed) {
         LOG(ERROR)
             << "SubmitDecode fails because we couldn't setup the protected "
diff --git a/media/video/h265_parser.cc b/media/video/h265_parser.cc
index 36d29d9..70653d7 100644
--- a/media/video/h265_parser.cc
+++ b/media/video/h265_parser.cc
@@ -670,6 +670,7 @@
     TRUE_OR_RETURN(sps->pcm_sample_bit_depth_chroma_minus1 + 1 <=
                    sps->bit_depth_c);
     READ_UE_OR_RETURN(&sps->log2_min_pcm_luma_coding_block_size_minus3);
+    IN_RANGE_OR_RETURN(sps->log2_min_pcm_luma_coding_block_size_minus3, 0, 2);
     int log2_min_ipcm_cb_size_y =
         sps->log2_min_pcm_luma_coding_block_size_minus3 + 3;
     IN_RANGE_OR_RETURN(log2_min_ipcm_cb_size_y, std::min(min_cb_log2_size_y, 5),
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 4fa8025..4f610c5 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -169,6 +169,8 @@
     "base/url_util.h",
     "cert/asn1_util.cc",
     "cert/asn1_util.h",
+    "cert/cert_and_ct_verifier.cc",
+    "cert/cert_and_ct_verifier.h",
     "cert/cert_database.cc",
     "cert/cert_database.h",
     "cert/cert_status_flags.cc",
@@ -4150,6 +4152,7 @@
     "base/upload_file_element_reader_unittest.cc",
     "base/url_util_unittest.cc",
     "cert/caching_cert_verifier_unittest.cc",
+    "cert/cert_and_ct_verifier_unittest.cc",
     "cert/cert_verifier_unittest.cc",
     "cert/cert_verify_proc_builtin_unittest.cc",
     "cert/cert_verify_proc_unittest.cc",
diff --git a/net/base/schemeful_site.h b/net/base/schemeful_site.h
index 0cda2446..b76a55e5 100644
--- a/net/base/schemeful_site.h
+++ b/net/base/schemeful_site.h
@@ -28,6 +28,8 @@
 
 namespace net {
 
+class SiteForCookies;
+
 // Class which represents a scheme and etld+1 for an origin, as specified by
 // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
 //
@@ -91,6 +93,9 @@
   friend struct mojo::StructTraits<network::mojom::SchemefulSiteDataView,
                                    SchemefulSite>;
 
+  // Create SiteForCookies from SchemefulSite needs to access internal origin.
+  friend class SiteForCookies;
+
   // Needed to serialize opaque and non-transient NetworkIsolationKeys, which
   // use opaque origins.
   friend class NetworkIsolationKey;
diff --git a/net/cert/cert_and_ct_verifier.cc b/net/cert/cert_and_ct_verifier.cc
new file mode 100644
index 0000000..fd79ee3
--- /dev/null
+++ b/net/cert/cert_and_ct_verifier.cc
@@ -0,0 +1,67 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/cert_and_ct_verifier.h"
+
+#include "base/callback.h"
+#include "net/cert/ct_verifier.h"
+
+namespace net {
+
+CertAndCTVerifier::CertAndCTVerifier(
+    std::unique_ptr<CertVerifier> cert_verifier,
+    std::unique_ptr<CTVerifier> ct_verifier)
+    : cert_verifier_(std::move(cert_verifier)),
+      ct_verifier_(std::move(ct_verifier)) {}
+
+CertAndCTVerifier::~CertAndCTVerifier() = default;
+
+int CertAndCTVerifier::Verify(const RequestParams& params,
+                              CertVerifyResult* verify_result,
+                              CompletionOnceCallback callback,
+                              std::unique_ptr<Request>* out_req,
+                              const NetLogWithSource& net_log) {
+  // It's safe to use |base::Unretained| here, because if this object is
+  // deleted, |cert_verifier_| will be deleted and this callback will not
+  // be invoked.
+  // It's not necessary to wrap |out_req|, because if |out_req| is deleted,
+  // this callback will be Reset(), which will also Reset |callback|, because it
+  // is moved and bound to |ct_callback|.
+  CompletionOnceCallback ct_callback = base::BindOnce(
+      &CertAndCTVerifier::OnCertVerifyComplete, base::Unretained(this), params,
+      std::move(callback), verify_result, net_log);
+
+  int result = cert_verifier_->Verify(params, verify_result,
+                                      std::move(ct_callback), out_req, net_log);
+
+  if (result != ERR_IO_PENDING) {
+    // Synchronous completion; directly perform CT verification which is always
+    // synchronous as it has all the data it needs for SCT verificiation and
+    // does not do any external communication.
+    ct_verifier_->Verify(params.hostname(), verify_result->verified_cert.get(),
+                         params.ocsp_response(), params.sct_list(),
+                         &verify_result->scts, net_log);
+  }
+
+  return result;
+}
+
+void CertAndCTVerifier::SetConfig(const Config& config) {
+  cert_verifier_->SetConfig(config);
+}
+
+void CertAndCTVerifier::OnCertVerifyComplete(const RequestParams& params,
+                                             CompletionOnceCallback callback,
+                                             CertVerifyResult* verify_result,
+                                             const NetLogWithSource& net_log,
+                                             int error) {
+  ct_verifier_->Verify(params.hostname(), verify_result->verified_cert.get(),
+                       params.ocsp_response(), params.sct_list(),
+                       &verify_result->scts, net_log);
+
+  // Now chain to the user's callback, which may delete |this|.
+  std::move(callback).Run(error);
+}
+
+}  // namespace net
diff --git a/net/cert/cert_and_ct_verifier.h b/net/cert/cert_and_ct_verifier.h
new file mode 100644
index 0000000..7905a55
--- /dev/null
+++ b/net/cert/cert_and_ct_verifier.h
@@ -0,0 +1,54 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_CERT_AND_CT_VERIFIER_H_
+#define NET_CERT_CERT_AND_CT_VERIFIER_H_
+
+#include <memory>
+
+#include "net/base/completion_once_callback.h"
+#include "net/base/net_export.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cert/cert_verify_result.h"
+#include "net/log/net_log_with_source.h"
+
+namespace net {
+
+class CTVerifier;
+
+// CertVerifier that also performs certificate transparency (CT) verification.
+class NET_EXPORT CertAndCTVerifier : public CertVerifier {
+ public:
+  // Creates a CertAndCTVerifier that will use |cert_verifier| to perform the
+  // actual underlying cert verification and |ct_verifier| to perform the CT
+  // verification.
+  CertAndCTVerifier(std::unique_ptr<CertVerifier> cert_verifier,
+                    std::unique_ptr<CTVerifier> ct_verifier);
+
+  ~CertAndCTVerifier() override;
+  CertAndCTVerifier(const CertAndCTVerifier&) = delete;
+  CertAndCTVerifier& operator=(const CertAndCTVerifier&) = delete;
+
+  // CertVerifier implementation:
+  int Verify(const RequestParams& params,
+             CertVerifyResult* verify_result,
+             CompletionOnceCallback callback,
+             std::unique_ptr<Request>* out_req,
+             const NetLogWithSource& net_log) override;
+  void SetConfig(const Config& config) override;
+
+ private:
+  void OnCertVerifyComplete(const RequestParams& params,
+                            CompletionOnceCallback callback,
+                            CertVerifyResult* verify_result,
+                            const NetLogWithSource& net_log,
+                            int error);
+
+  std::unique_ptr<CertVerifier> cert_verifier_;
+  std::unique_ptr<CTVerifier> ct_verifier_;
+};
+
+}  // namespace net
+
+#endif  // NET_CERT_CERT_AND_CT_VERIFIER_H_
diff --git a/net/cert/cert_and_ct_verifier_unittest.cc b/net/cert/cert_and_ct_verifier_unittest.cc
new file mode 100644
index 0000000..77bc7fa
--- /dev/null
+++ b/net/cert/cert_and_ct_verifier_unittest.cc
@@ -0,0 +1,302 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/cert_and_ct_verifier.h"
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "net/base/completion_once_callback.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cert/cert_verify_result.h"
+#include "net/cert/ct_verifier.h"
+#include "net/cert/mock_cert_verifier.h"
+#include "net/cert/sct_status_flags.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "net/log/net_log_with_source.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/ct_test_util.h"
+#include "net/test/gtest_util.h"
+#include "net/test/test_data_directory.h"
+#include "net/test/test_with_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using net::test::IsError;
+using net::test::IsOk;
+
+namespace net {
+
+namespace {
+
+// Callback that allows a test to check that the callback was canceled. The
+// FailTest() callback can own the CallbackHelper while the test keeps a WeakPtr
+// to check whether it has been deleted. The callback itself will fail the test
+// if it is run.
+struct CallbackHelper {
+  base::WeakPtrFactory<CallbackHelper> factory{this};
+};
+void FailTest(std::unique_ptr<CallbackHelper> helper, int result) {
+  FAIL();
+}
+
+class FakeCTVerifier : public CTVerifier {
+ public:
+  // CTVerifier implementation:
+  void Verify(base::StringPiece hostname,
+              X509Certificate* cert,
+              base::StringPiece stapled_ocsp_response,
+              base::StringPiece sct_list_from_tls_extension,
+              SignedCertificateTimestampAndStatusList* output_scts,
+              const NetLogWithSource& net_log) override {
+    *output_scts = scts_;
+  }
+
+  // Test setup interface:
+  void set_scts(const SignedCertificateTimestampAndStatusList& scts) {
+    scts_ = scts;
+  }
+
+ private:
+  SignedCertificateTimestampAndStatusList scts_;
+};
+
+}  // namespace
+
+class CertAndCTVerifierTest : public TestWithTaskEnvironment {
+ public:
+  CertAndCTVerifierTest() {}
+  ~CertAndCTVerifierTest() override = default;
+};
+
+// Tests that both certificate and certificate transparency details in the
+// CertVerifyResult are filled by the CertAndCTVerifier, when completion occurs
+// synchronously.
+TEST_F(CertAndCTVerifierTest, CertAndCTDetailsFilled_Sync) {
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "ok_cert.pem"));
+  ASSERT_TRUE(test_cert.get());
+
+  // Mock the cert verification and CT verification results.
+  CertVerifyResult mock_result;
+  mock_result.cert_status = OK;
+  mock_result.verified_cert = test_cert;
+  auto cert_verifier = std::make_unique<MockCertVerifier>();
+  cert_verifier->AddResultForCert(test_cert, mock_result, OK);
+  cert_verifier->set_async(false);
+
+  scoped_refptr<ct::SignedCertificateTimestamp> sct;
+  ct::GetX509CertSCT(&sct);
+  SignedCertificateTimestampAndStatus sct_and_status(sct, ct::SCT_STATUS_OK);
+  SignedCertificateTimestampAndStatusList sct_list{sct_and_status};
+  auto ct_verifier = std::make_unique<FakeCTVerifier>();
+  ct_verifier->set_scts(sct_list);
+
+  CertAndCTVerifier cert_and_ct_verifier(std::move(cert_verifier),
+                                         std::move(ct_verifier));
+
+  CertVerifyResult verify_result;
+  TestCompletionCallback callback;
+  std::unique_ptr<CertVerifier::Request> request;
+
+  int result = callback.GetResult(cert_and_ct_verifier.Verify(
+      CertVerifier::RequestParams(test_cert, "www.example.com", 0,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string()),
+      &verify_result, callback.callback(), &request, NetLogWithSource()));
+  EXPECT_THAT(result, IsOk());
+  ASSERT_EQ(1u, verify_result.scts.size());
+  EXPECT_EQ(ct::SCT_STATUS_OK, verify_result.scts[0].status);
+}
+
+// Tests that both certificate and certificate transparency details in the
+// CertVerifyResult are filled by the CertAndCTVerifier, when completion occurs
+// asynchronously.
+TEST_F(CertAndCTVerifierTest, CertAndCTDetailsFilled_Async) {
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "ok_cert.pem"));
+  ASSERT_TRUE(test_cert.get());
+
+  // Mock the cert verification and CT verification results.
+  CertVerifyResult mock_result;
+  mock_result.cert_status = OK;
+  mock_result.verified_cert = test_cert;
+  auto cert_verifier = std::make_unique<MockCertVerifier>();
+  cert_verifier->AddResultForCert(test_cert, mock_result, OK);
+  cert_verifier->set_async(true);
+
+  scoped_refptr<ct::SignedCertificateTimestamp> sct;
+  ct::GetX509CertSCT(&sct);
+  SignedCertificateTimestampAndStatus sct_and_status(sct, ct::SCT_STATUS_OK);
+  SignedCertificateTimestampAndStatusList sct_list{sct_and_status};
+  auto ct_verifier = std::make_unique<FakeCTVerifier>();
+  ct_verifier->set_scts(sct_list);
+
+  CertAndCTVerifier cert_and_ct_verifier(std::move(cert_verifier),
+                                         std::move(ct_verifier));
+
+  CertVerifyResult verify_result;
+  TestCompletionCallback callback;
+  std::unique_ptr<CertVerifier::Request> request;
+
+  int result = callback.GetResult(cert_and_ct_verifier.Verify(
+      CertVerifier::RequestParams(test_cert, "www.example.com", 0,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string()),
+      &verify_result, callback.callback(), &request, NetLogWithSource()));
+  EXPECT_THAT(result, IsOk());
+  ASSERT_EQ(1u, verify_result.scts.size());
+  EXPECT_EQ(ct::SCT_STATUS_OK, verify_result.scts[0].status);
+}
+
+// Tests that the callback of a canceled request is never run.
+TEST_F(CertAndCTVerifierTest, CancelRequest) {
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "ok_cert.pem"));
+  ASSERT_TRUE(test_cert.get());
+
+  // Mock the cert verification and CT verification results.
+  CertVerifyResult mock_result;
+  mock_result.cert_status = OK;
+  mock_result.verified_cert = test_cert;
+  auto cert_verifier = std::make_unique<MockCertVerifier>();
+  cert_verifier->AddResultForCert(test_cert, mock_result, OK);
+  cert_verifier->set_async(true);
+
+  scoped_refptr<ct::SignedCertificateTimestamp> sct;
+  ct::GetX509CertSCT(&sct);
+  SignedCertificateTimestampAndStatus sct_and_status(sct, ct::SCT_STATUS_OK);
+  SignedCertificateTimestampAndStatusList sct_list{sct_and_status};
+  auto ct_verifier = std::make_unique<FakeCTVerifier>();
+  ct_verifier->set_scts(sct_list);
+
+  CertAndCTVerifier cert_and_ct_verifier(std::move(cert_verifier),
+                                         std::move(ct_verifier));
+
+  CertVerifyResult verify_result;
+  std::unique_ptr<CertVerifier::Request> request;
+
+  auto helper = std::make_unique<CallbackHelper>();
+  base::WeakPtr<CallbackHelper> weak_helper = helper->factory.GetWeakPtr();
+
+  int result = cert_and_ct_verifier.Verify(
+      CertVerifier::RequestParams(test_cert, "www.example.com", 0,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string()),
+      &verify_result, base::BindOnce(&FailTest, std::move(helper)), &request,
+      NetLogWithSource());
+  ASSERT_THAT(result, IsError(ERR_IO_PENDING));
+  ASSERT_TRUE(request);
+  request.reset();
+
+  // Check that the callback was reset when the request was reset.
+  ASSERT_TRUE(weak_helper.WasInvalidated());
+
+  RunUntilIdle();
+}
+
+// Tests that the callback of a request is never run if the CertAndCTVerifier is
+// deleted.
+TEST_F(CertAndCTVerifierTest, DeleteVerifier) {
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "ok_cert.pem"));
+  ASSERT_TRUE(test_cert.get());
+
+  // Mock the cert verification and CT verification results.
+  CertVerifyResult mock_result;
+  mock_result.cert_status = OK;
+  mock_result.verified_cert = test_cert;
+  auto cert_verifier = std::make_unique<MockCertVerifier>();
+  cert_verifier->AddResultForCert(test_cert, mock_result, OK);
+  cert_verifier->set_async(true);
+
+  scoped_refptr<ct::SignedCertificateTimestamp> sct;
+  ct::GetX509CertSCT(&sct);
+  SignedCertificateTimestampAndStatus sct_and_status(sct, ct::SCT_STATUS_OK);
+  SignedCertificateTimestampAndStatusList sct_list{sct_and_status};
+  auto ct_verifier = std::make_unique<FakeCTVerifier>();
+  ct_verifier->set_scts(sct_list);
+
+  auto cert_and_ct_verifier = std::make_unique<CertAndCTVerifier>(
+      std::move(cert_verifier), std::move(ct_verifier));
+
+  CertVerifyResult verify_result;
+  std::unique_ptr<CertVerifier::Request> request;
+
+  auto helper = std::make_unique<CallbackHelper>();
+  base::WeakPtr<CallbackHelper> weak_helper = helper->factory.GetWeakPtr();
+
+  int result = cert_and_ct_verifier->Verify(
+      CertVerifier::RequestParams(test_cert, "www.example.com", 0,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string()),
+      &verify_result, base::BindOnce(&FailTest, std::move(helper)), &request,
+      NetLogWithSource());
+  ASSERT_THAT(result, IsError(ERR_IO_PENDING));
+  ASSERT_TRUE(request);
+  cert_and_ct_verifier.reset();
+
+  // Check that the callback was reset when the verifier was deleted.
+  ASSERT_TRUE(weak_helper.WasInvalidated());
+
+  RunUntilIdle();
+}
+
+// Tests that cancelling the request and stopping without ever running anything
+// works as expected.
+TEST_F(CertAndCTVerifierTest, CancelRequestThenQuit) {
+  base::FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> test_cert(
+      ImportCertFromFile(certs_dir, "ok_cert.pem"));
+  ASSERT_TRUE(test_cert.get());
+
+  // Mock the cert verification and CT verification results.
+  CertVerifyResult mock_result;
+  mock_result.cert_status = OK;
+  mock_result.verified_cert = test_cert;
+  auto cert_verifier = std::make_unique<MockCertVerifier>();
+  cert_verifier->AddResultForCert(test_cert, mock_result, OK);
+  cert_verifier->set_async(true);
+
+  scoped_refptr<ct::SignedCertificateTimestamp> sct;
+  ct::GetX509CertSCT(&sct);
+  SignedCertificateTimestampAndStatus sct_and_status(sct, ct::SCT_STATUS_OK);
+  SignedCertificateTimestampAndStatusList sct_list{sct_and_status};
+  auto ct_verifier = std::make_unique<FakeCTVerifier>();
+  ct_verifier->set_scts(sct_list);
+
+  auto cert_and_ct_verifier = std::make_unique<CertAndCTVerifier>(
+      std::move(cert_verifier), std::move(ct_verifier));
+
+  CertVerifyResult verify_result;
+  std::unique_ptr<CertVerifier::Request> request;
+
+  auto helper = std::make_unique<CallbackHelper>();
+  base::WeakPtr<CallbackHelper> weak_helper = helper->factory.GetWeakPtr();
+
+  int result = cert_and_ct_verifier->Verify(
+      CertVerifier::RequestParams(test_cert, "www.example.com", 0,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string()),
+      &verify_result, base::BindOnce(&FailTest, std::move(helper)), &request,
+      NetLogWithSource());
+  ASSERT_THAT(result, IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request);
+  request.reset();
+
+  // Check that the callback was reset when the request was reset.
+  ASSERT_TRUE(weak_helper.WasInvalidated());
+
+  // Destroy |cert_and_ct_verifier| by going out of scope.
+}
+
+}  // namespace net
diff --git a/net/cert/mock_cert_verifier.cc b/net/cert/mock_cert_verifier.cc
index 1660818..19a5a96 100644
--- a/net/cert/mock_cert_verifier.cc
+++ b/net/cert/mock_cert_verifier.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/callback_list.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
@@ -42,8 +43,13 @@
 
 class MockCertVerifier::MockRequest : public CertVerifier::Request {
  public:
-  MockRequest(CertVerifyResult* result, CompletionOnceCallback callback)
-      : result_(result), callback_(std::move(callback)) {}
+  MockRequest(MockCertVerifier* parent,
+              CertVerifyResult* result,
+              CompletionOnceCallback callback)
+      : result_(result), callback_(std::move(callback)) {
+    subscription_ = parent->request_list_.Add(
+        base::BindOnce(&MockRequest::Cleanup, weak_factory_.GetWeakPtr()));
+  }
 
   void ReturnResultLater(int rv, const CertVerifyResult& result) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -53,19 +59,35 @@
 
  private:
   void ReturnResult(int rv, const CertVerifyResult& result) {
+    // If the MockCertVerifier has been deleted, the callback will have been
+    // reset to null.
+    if (!callback_)
+      return;
+
     *result_ = result;
     std::move(callback_).Run(rv);
   }
 
+  void Cleanup() {
+    // Note: May delete |this_|.
+    std::move(callback_).Reset();
+  }
+
   CertVerifyResult* result_;
   CompletionOnceCallback callback_;
+  base::CallbackListSubscription subscription_;
+
   base::WeakPtrFactory<MockRequest> weak_factory_{this};
 };
 
 MockCertVerifier::MockCertVerifier()
     : default_result_(ERR_CERT_INVALID), async_(false) {}
 
-MockCertVerifier::~MockCertVerifier() = default;
+MockCertVerifier::~MockCertVerifier() {
+  // Reset the callbacks for any outstanding MockRequests to fulfill the
+  // respective net::CertVerifier contract.
+  request_list_.Notify();
+}
 
 int MockCertVerifier::Verify(const RequestParams& params,
                              CertVerifyResult* verify_result,
@@ -77,7 +99,7 @@
   }
 
   auto request =
-      std::make_unique<MockRequest>(verify_result, std::move(callback));
+      std::make_unique<MockRequest>(this, verify_result, std::move(callback));
   CertVerifyResult result;
   int rv = VerifyImpl(params, &result);
   request->ReturnResultLater(rv, result);
diff --git a/net/cert/mock_cert_verifier.h b/net/cert/mock_cert_verifier.h
index 66b82c7..f653fe37 100644
--- a/net/cert/mock_cert_verifier.h
+++ b/net/cert/mock_cert_verifier.h
@@ -8,6 +8,7 @@
 #include <list>
 #include <memory>
 
+#include "base/callback_list.h"
 #include "net/base/completion_once_callback.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/cert_verify_result.h"
@@ -65,12 +66,15 @@
   struct Rule;
   using RuleList = std::list<Rule>;
   class MockRequest;
+  friend class MockRequest;
 
   int VerifyImpl(const RequestParams& params, CertVerifyResult* verify_result);
 
   int default_result_;
   RuleList rules_;
   bool async_;
+
+  base::OnceClosureList request_list_;
 };
 
 }  // namespace net
diff --git a/net/cert_net/cert_net_fetcher_url_request_unittest.cc b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
index 08e92be..1ccfb9b 100644
--- a/net/cert_net/cert_net_fetcher_url_request_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
@@ -56,8 +56,6 @@
     storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
     storage_.set_transport_security_state(
         std::make_unique<TransportSecurityState>());
-    storage_.set_cert_transparency_verifier(
-        std::make_unique<MultiLogCTVerifier>());
     storage_.set_ct_policy_enforcer(
         std::make_unique<DefaultCTPolicyEnforcer>());
     storage_.set_proxy_resolution_service(
@@ -73,7 +71,6 @@
     session_context.host_resolver = host_resolver();
     session_context.cert_verifier = cert_verifier();
     session_context.transport_security_state = transport_security_state();
-    session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
     session_context.proxy_resolution_service = proxy_resolution_service();
     session_context.ssl_config_service = ssl_config_service();
diff --git a/net/cookies/site_for_cookies.cc b/net/cookies/site_for_cookies.cc
index 759b4e7..d4cd2cf10 100644
--- a/net/cookies/site_for_cookies.cc
+++ b/net/cookies/site_for_cookies.cc
@@ -139,6 +139,11 @@
   return scheme_.empty();
 }
 
+SiteForCookies::SiteForCookies(const net::SchemefulSite& schemeful_site)
+    : scheme_(schemeful_site.site_as_origin_.scheme()),
+      registrable_domain_(schemeful_site.site_as_origin_.host()),
+      schemefully_same_(!scheme_.empty()) {}
+
 SiteForCookies::SiteForCookies(const std::string& scheme,
                                const std::string& host)
     : scheme_(scheme),
diff --git a/net/cookies/site_for_cookies.h b/net/cookies/site_for_cookies.h
index 0de33fab..68628b1f 100644
--- a/net/cookies/site_for_cookies.h
+++ b/net/cookies/site_for_cookies.h
@@ -9,6 +9,7 @@
 
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
+#include "net/base/schemeful_site.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -38,6 +39,8 @@
   SiteForCookies(const SiteForCookies& other);
   SiteForCookies(SiteForCookies&& other);
 
+  explicit SiteForCookies(const SchemefulSite& schemeful_site);
+
   ~SiteForCookies();
 
   SiteForCookies& operator=(const SiteForCookies& other);
diff --git a/net/cookies/site_for_cookies_unittest.cc b/net/cookies/site_for_cookies_unittest.cc
index 640b9987..388e528 100644
--- a/net/cookies/site_for_cookies_unittest.cc
+++ b/net/cookies/site_for_cookies_unittest.cc
@@ -403,5 +403,27 @@
   }
 }
 
+TEST_F(SchemefulSiteForCookiesTest, SchemefulSite) {
+  const char* kTestCases[] = {"opaque.com",
+                              "http://a.com",
+                              "https://sub1.example.com:42/something",
+                              "https://a.com",
+                              "ws://a.com",
+                              "wss://a.com",
+                              "file://a.com",
+                              "file://folder1/folder2/file.txt",
+                              "file:///file.txt"};
+
+  for (std::string url : kTestCases) {
+    url::Origin origin = url::Origin::Create(GURL(url));
+    SiteForCookies from_origin = SiteForCookies::FromOrigin(origin);
+    SchemefulSite schemeful_site = SchemefulSite(origin);
+    SiteForCookies from_schemeful_site = SiteForCookies(schemeful_site);
+
+    EXPECT_TRUE(from_origin.IsEquivalent(from_schemeful_site));
+    EXPECT_TRUE(from_schemeful_site.IsEquivalent(from_origin));
+  }
+}
+
 }  // namespace
 }  // namespace net
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 7e45ccb..25ba5ba 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/strings/stringprintf.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties.h"
@@ -55,7 +54,6 @@
     session_context.host_resolver = &host_resolver_;
     session_context.cert_verifier = cert_verifier_.get();
     session_context.transport_security_state = transport_security_state_.get();
-    session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.ssl_config_service = ssl_config_service_.get();
@@ -269,7 +267,6 @@
   MockHostResolver host_resolver_;
   std::unique_ptr<CertVerifier> cert_verifier_;
   std::unique_ptr<TransportSecurityState> transport_security_state_;
-  MultiLogCTVerifier ct_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<SSLConfigService> ssl_config_service_;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 6dd71b0..e9c5c63 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -109,7 +109,6 @@
       host_resolver(nullptr),
       cert_verifier(nullptr),
       transport_security_state(nullptr),
-      cert_transparency_verifier(nullptr),
       ct_policy_enforcer(nullptr),
       sct_auditing_delegate(nullptr),
       proxy_resolution_service(nullptr),
@@ -153,7 +152,6 @@
       ssl_client_context_(context.ssl_config_service,
                           context.cert_verifier,
                           context.transport_security_state,
-                          context.cert_transparency_verifier,
                           context.ct_policy_enforcer,
                           &ssl_client_session_cache_,
                           context.sct_auditing_delegate),
@@ -168,7 +166,6 @@
                            context.cert_verifier,
                            context.ct_policy_enforcer,
                            context.transport_security_state,
-                           context.cert_transparency_verifier,
                            context.sct_auditing_delegate,
                            context.socket_performance_watcher_factory,
                            context.quic_crypto_client_stream_factory,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index a57b489..9c6dd62 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -51,7 +51,6 @@
 class ClientSocketFactory;
 class ClientSocketPool;
 class ClientSocketPoolManager;
-class CTVerifier;
 class HostResolver;
 class HttpAuthHandlerFactory;
 class HttpNetworkSessionPeer;
@@ -165,7 +164,6 @@
     HostResolver* host_resolver;
     CertVerifier* cert_verifier;
     TransportSecurityState* transport_security_state;
-    CTVerifier* cert_transparency_verifier;
     CTPolicyEnforcer* ct_policy_enforcer;
     SCTAuditingDelegate* sct_auditing_delegate;
     ProxyResolutionService* proxy_resolution_service;
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index fbe81ff7..9380e879 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -23,7 +23,6 @@
 #include "net/base/test_completion_callback.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties.h"
 #include "net/http/http_stream.h"
@@ -249,7 +248,6 @@
     context.http_server_properties = http_server_properties_.get();
     context.cert_verifier = &cert_verifier_;
     context.transport_security_state = &transport_security_state_;
-    context.cert_transparency_verifier = &ct_verifier_;
     context.ct_policy_enforcer = &ct_policy_enforcer_;
     context.quic_context = &quic_context_;
     return new HttpNetworkSession(HttpNetworkSession::Params(), context);
@@ -260,7 +258,6 @@
   std::unique_ptr<HttpServerProperties> http_server_properties_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  MultiLogCTVerifier ct_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   QuicContext quic_context_;
   const std::unique_ptr<HttpNetworkSession> session_;
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 929ed191..866b108 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -849,8 +849,6 @@
     session_context.cert_verifier = &cert_verifier;
     TransportSecurityState transport_security_state;
     session_context.transport_security_state = &transport_security_state;
-    MultiLogCTVerifier ct_verifier;
-    session_context.cert_transparency_verifier = &ct_verifier;
     DefaultCTPolicyEnforcer ct_policy_enforcer;
     QuicContext quic_context;
     session_context.ct_policy_enforcer = &ct_policy_enforcer;
@@ -2028,7 +2026,6 @@
     session_context.quic_crypto_client_stream_factory =
         &crypto_client_stream_factory_;
     session_context.transport_security_state = &transport_security_state_;
-    session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context.host_resolver = &host_resolver_;
     session_context.proxy_resolution_service = proxy_resolution_service_.get();
@@ -2083,7 +2080,6 @@
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
   HttpServerProperties http_server_properties_;
   TransportSecurityState transport_security_state_;
-  MultiLogCTVerifier ct_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   MockHostResolver host_resolver_;
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
@@ -3134,7 +3130,6 @@
     session_context_.host_resolver = &host_resolver_;
     session_context_.cert_verifier = &cert_verifier_;
     session_context_.transport_security_state = &transport_security_state_;
-    session_context_.cert_transparency_verifier = &ct_verifier_;
     session_context_.client_socket_factory = &socket_factory_;
     session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context_.ssl_config_service = &ssl_config_service_;
@@ -3157,7 +3152,6 @@
   MockHostResolver host_resolver_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  MultiLogCTVerifier ct_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
 };
 
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index 784bcb0..8d9fa834 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -84,8 +84,6 @@
     storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
     storage_.set_transport_security_state(
         std::make_unique<TransportSecurityState>());
-    storage_.set_cert_transparency_verifier(
-        std::make_unique<MultiLogCTVerifier>());
     storage_.set_ct_policy_enforcer(
         std::make_unique<DefaultCTPolicyEnforcer>());
     storage_.set_proxy_resolution_service(
@@ -101,7 +99,6 @@
     session_context.host_resolver = host_resolver();
     session_context.cert_verifier = cert_verifier();
     session_context.transport_security_state = transport_security_state();
-    session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
     session_context.proxy_resolution_service = proxy_resolution_service();
     session_context.ssl_config_service = ssl_config_service();
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index ed73075..1a198cb8 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -54,7 +54,6 @@
       CertVerifier* cert_verifier,
       CTPolicyEnforcer* ct_policy_enforcer,
       TransportSecurityState* transport_security_state,
-      CTVerifier* cert_transparency_verifier,
       SCTAuditingDelegate* sct_auditing_delegate,
       int cert_verify_flags,
       const NetLogWithSource& net_log);
@@ -124,6 +123,8 @@
 
   bool ShouldAllowUnknownRootForHost(const std::string& hostname);
 
+  int CheckCTCompliance();
+
   // Proof verifier to notify when this jobs completes.
   ProofVerifierChromium* proof_verifier_;
 
@@ -135,8 +136,6 @@
 
   TransportSecurityState* transport_security_state_;
 
-  CTVerifier* cert_transparency_verifier_;
-
   SCTAuditingDelegate* sct_auditing_delegate_;
 
   // |hostname| specifies the hostname for which |certs| is a valid chain.
@@ -173,7 +172,6 @@
     CertVerifier* cert_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
     TransportSecurityState* transport_security_state,
-    CTVerifier* cert_transparency_verifier,
     SCTAuditingDelegate* sct_auditing_delegate,
     int cert_verify_flags,
     const NetLogWithSource& net_log)
@@ -181,7 +179,6 @@
       verifier_(cert_verifier),
       policy_enforcer_(ct_policy_enforcer),
       transport_security_state_(transport_security_state),
-      cert_transparency_verifier_(cert_transparency_verifier),
       sct_auditing_delegate_(sct_auditing_delegate),
       cert_verify_flags_(cert_verify_flags),
       next_state_(STATE_NONE),
@@ -191,7 +188,6 @@
   CHECK(verifier_);
   CHECK(policy_enforcer_);
   CHECK(transport_security_state_);
-  CHECK(cert_transparency_verifier_);
 }
 
 ProofVerifierChromium::Job::~Job() {
@@ -405,96 +401,7 @@
   // If the connection was good, check HPKP and CT status simultaneously,
   // but prefer to treat the HPKP error as more serious, if there was one.
   if (result == OK) {
-    // Note that this is a completely synchronous operation: The CT Log Verifier
-    // gets all the data it needs for SCT verification and does not do any
-    // external communication.
-    cert_transparency_verifier_->Verify(
-        hostname_, cert_.get(), std::string(), cert_sct_,
-        &verify_details_->cert_verify_result.scts, net_log_);
-
-    ct::SCTList verified_scts;
-    for (const auto& sct_and_status : cert_verify_result.scts) {
-      if (sct_and_status.status == ct::SCT_STATUS_OK)
-        verified_scts.push_back(sct_and_status.sct);
-    }
-    verify_details_->cert_verify_result.policy_compliance =
-        policy_enforcer_->CheckCompliance(
-            cert_verify_result.verified_cert.get(), verified_scts, net_log_);
-    if (verify_details_->cert_verify_result.cert_status & CERT_STATUS_IS_EV) {
-      if (verify_details_->cert_verify_result.policy_compliance !=
-              ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
-          verify_details_->cert_verify_result.policy_compliance !=
-              ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
-        verify_details_->cert_verify_result.cert_status |=
-            CERT_STATUS_CT_COMPLIANCE_FAILED;
-        verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
-      }
-
-      // Record the CT compliance status for connections with EV certificates,
-      // to distinguish how often EV status is being dropped due to failing CT
-      // compliance.
-      if (verify_details_->cert_verify_result.is_issued_by_known_root) {
-        UMA_HISTOGRAM_ENUMERATION(
-            "Net.CertificateTransparency.EVCompliance2.QUIC",
-            cert_verify_result.policy_compliance,
-            ct::CTPolicyCompliance::CT_POLICY_COUNT);
-      }
-    }
-
-    // Record the CT compliance of every connection to get an overall picture of
-    // how many connections are CT-compliant.
-    if (verify_details_->cert_verify_result.is_issued_by_known_root) {
-      UMA_HISTOGRAM_ENUMERATION(
-          "Net.CertificateTransparency.ConnectionComplianceStatus2.QUIC",
-          verify_details_->cert_verify_result.policy_compliance,
-          ct::CTPolicyCompliance::CT_POLICY_COUNT);
-    }
-
-    int ct_result = OK;
-    TransportSecurityState::CTRequirementsStatus ct_requirement_status =
-        transport_security_state_->CheckCTRequirements(
-            HostPortPair(hostname_, port_),
-            cert_verify_result.is_issued_by_known_root,
-            cert_verify_result.public_key_hashes,
-            cert_verify_result.verified_cert.get(), cert_.get(),
-            cert_verify_result.scts,
-            TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
-            cert_verify_result.policy_compliance,
-            proof_verifier_->network_isolation_key_);
-    if (ct_requirement_status != TransportSecurityState::CT_NOT_REQUIRED) {
-      if (verify_details_->cert_verify_result.is_issued_by_known_root) {
-        // Record the CT compliance of connections for which compliance is
-        // required; this helps answer the question: "Of all connections that
-        // are supposed to be serving valid CT information, how many fail to do
-        // so?"
-        UMA_HISTOGRAM_ENUMERATION(
-            "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2."
-            "QUIC",
-            cert_verify_result.policy_compliance,
-            ct::CTPolicyCompliance::CT_POLICY_COUNT);
-      }
-    }
-
-    if (sct_auditing_delegate_ &&
-        sct_auditing_delegate_->IsSCTAuditingEnabled() &&
-        cert_verify_result.is_issued_by_known_root) {
-      sct_auditing_delegate_->MaybeEnqueueReport(
-          HostPortPair(hostname_, port_),
-          cert_verify_result.verified_cert.get(), cert_verify_result.scts);
-    }
-
-    switch (ct_requirement_status) {
-      case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
-        verify_details_->cert_verify_result.cert_status |=
-            CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
-        ct_result = ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
-        break;
-      case TransportSecurityState::CT_REQUIREMENTS_MET:
-      case TransportSecurityState::CT_NOT_REQUIRED:
-        // Intentional fallthrough; this case is just here to make sure that all
-        // possible values of CheckCTRequirements() are handled.
-        break;
-    }
+    int ct_result = CheckCTCompliance();
     TransportSecurityState::PKPStatus pin_validity =
         transport_security_state_->CheckPublicKeyPins(
             HostPortPair(hostname_, port_),
@@ -595,25 +502,106 @@
   return true;
 }
 
+int ProofVerifierChromium::Job::CheckCTCompliance() {
+  const CertVerifyResult& cert_verify_result =
+      verify_details_->cert_verify_result;
+
+  ct::SCTList verified_scts;
+  for (const auto& sct_and_status : cert_verify_result.scts) {
+    if (sct_and_status.status == ct::SCT_STATUS_OK)
+      verified_scts.push_back(sct_and_status.sct);
+  }
+  verify_details_->cert_verify_result.policy_compliance =
+      policy_enforcer_->CheckCompliance(cert_verify_result.verified_cert.get(),
+                                        verified_scts, net_log_);
+  if (verify_details_->cert_verify_result.cert_status & CERT_STATUS_IS_EV) {
+    if (verify_details_->cert_verify_result.policy_compliance !=
+            ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
+        verify_details_->cert_verify_result.policy_compliance !=
+            ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
+      verify_details_->cert_verify_result.cert_status |=
+          CERT_STATUS_CT_COMPLIANCE_FAILED;
+      verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
+    }
+
+    // Record the CT compliance status for connections with EV certificates,
+    // to distinguish how often EV status is being dropped due to failing CT
+    // compliance.
+    if (verify_details_->cert_verify_result.is_issued_by_known_root) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Net.CertificateTransparency.EVCompliance2.QUIC",
+          cert_verify_result.policy_compliance,
+          ct::CTPolicyCompliance::CT_POLICY_COUNT);
+    }
+  }
+
+  // Record the CT compliance of every connection to get an overall picture of
+  // how many connections are CT-compliant.
+  if (verify_details_->cert_verify_result.is_issued_by_known_root) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Net.CertificateTransparency.ConnectionComplianceStatus2.QUIC",
+        verify_details_->cert_verify_result.policy_compliance,
+        ct::CTPolicyCompliance::CT_POLICY_COUNT);
+  }
+
+  TransportSecurityState::CTRequirementsStatus ct_requirement_status =
+      transport_security_state_->CheckCTRequirements(
+          HostPortPair(hostname_, port_),
+          cert_verify_result.is_issued_by_known_root,
+          cert_verify_result.public_key_hashes,
+          cert_verify_result.verified_cert.get(), cert_.get(),
+          cert_verify_result.scts,
+          TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+          cert_verify_result.policy_compliance,
+          proof_verifier_->network_isolation_key_);
+  if (ct_requirement_status != TransportSecurityState::CT_NOT_REQUIRED) {
+    if (verify_details_->cert_verify_result.is_issued_by_known_root) {
+      // Record the CT compliance of connections for which compliance is
+      // required; this helps answer the question: "Of all connections that
+      // are supposed to be serving valid CT information, how many fail to do
+      // so?"
+      UMA_HISTOGRAM_ENUMERATION(
+          "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2."
+          "QUIC",
+          cert_verify_result.policy_compliance,
+          ct::CTPolicyCompliance::CT_POLICY_COUNT);
+    }
+  }
+
+  if (sct_auditing_delegate_ &&
+      sct_auditing_delegate_->IsSCTAuditingEnabled()) {
+    sct_auditing_delegate_->MaybeEnqueueReport(
+        HostPortPair(hostname_, port_), cert_verify_result.verified_cert.get(),
+        cert_verify_result.scts);
+  }
+
+  switch (ct_requirement_status) {
+    case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
+      verify_details_->cert_verify_result.cert_status |=
+          CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
+      return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
+    case TransportSecurityState::CT_REQUIREMENTS_MET:
+    case TransportSecurityState::CT_NOT_REQUIRED:
+      return OK;
+  }
+}
+
 ProofVerifierChromium::ProofVerifierChromium(
     CertVerifier* cert_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
     TransportSecurityState* transport_security_state,
-    CTVerifier* cert_transparency_verifier,
     SCTAuditingDelegate* sct_auditing_delegate,
     std::set<std::string> hostnames_to_allow_unknown_roots,
     const NetworkIsolationKey& network_isolation_key)
     : cert_verifier_(cert_verifier),
       ct_policy_enforcer_(ct_policy_enforcer),
       transport_security_state_(transport_security_state),
-      cert_transparency_verifier_(cert_transparency_verifier),
       sct_auditing_delegate_(sct_auditing_delegate),
       hostnames_to_allow_unknown_roots_(hostnames_to_allow_unknown_roots),
       network_isolation_key_(network_isolation_key) {
   DCHECK(cert_verifier_);
   DCHECK(ct_policy_enforcer_);
   DCHECK(transport_security_state_);
-  DCHECK(cert_transparency_verifier_);
 }
 
 ProofVerifierChromium::~ProofVerifierChromium() {}
@@ -640,8 +628,8 @@
       reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
   std::unique_ptr<Job> job = std::make_unique<Job>(
       this, cert_verifier_, ct_policy_enforcer_, transport_security_state_,
-      cert_transparency_verifier_, sct_auditing_delegate_,
-      chromium_context->cert_verify_flags, chromium_context->net_log);
+      sct_auditing_delegate_, chromium_context->cert_verify_flags,
+      chromium_context->net_log);
   quic::QuicAsyncStatus status = job->VerifyProof(
       hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
       signature, error_details, verify_details, std::move(callback));
@@ -671,8 +659,8 @@
       reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
   std::unique_ptr<Job> job = std::make_unique<Job>(
       this, cert_verifier_, ct_policy_enforcer_, transport_security_state_,
-      cert_transparency_verifier_, sct_auditing_delegate_,
-      chromium_context->cert_verify_flags, chromium_context->net_log);
+      sct_auditing_delegate_, chromium_context->cert_verify_flags,
+      chromium_context->net_log);
   quic::QuicAsyncStatus status =
       job->VerifyCertChain(hostname, port, certs, ocsp_response, cert_sct,
                            error_details, verify_details, std::move(callback));
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 4e361aa..2257541e 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -23,7 +23,6 @@
 
 class CTPolicyEnforcer;
 class CertVerifier;
-class CTVerifier;
 class SCTAuditingDelegate;
 class TransportSecurityState;
 
@@ -73,7 +72,6 @@
   ProofVerifierChromium(CertVerifier* cert_verifier,
                         CTPolicyEnforcer* ct_policy_enforcer,
                         TransportSecurityState* transport_security_state,
-                        CTVerifier* cert_transparency_verifier,
                         SCTAuditingDelegate* sct_auditing_delegate,
                         std::set<std::string> hostnames_to_allow_unknown_roots,
                         const NetworkIsolationKey& network_isolation_key);
@@ -119,7 +117,6 @@
   CTPolicyEnforcer* const ct_policy_enforcer_;
 
   TransportSecurityState* const transport_security_state_;
-  CTVerifier* const cert_transparency_verifier_;
 
   SCTAuditingDelegate* const sct_auditing_delegate_;
 
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc
index a5f18ac8..e62a038 100644
--- a/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -4,6 +4,7 @@
 
 #include "net/quic/crypto/proof_verifier_chromium.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/memory/ref_counted.h"
@@ -12,6 +13,7 @@
 #include "net/base/completion_once_callback.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_isolation_key.h"
+#include "net/cert/cert_and_ct_verifier.h"
 #include "net/cert/cert_status_flags.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_log_verifier.h"
@@ -174,14 +176,6 @@
         .WillRepeatedly(
             Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-    scoped_refptr<const CTLogVerifier> log(
-        CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
-    ASSERT_TRUE(log);
-    log_verifiers_.push_back(log);
-
-    ct_verifier_.reset(new MultiLogCTVerifier());
-    ct_verifier_->AddLogs(log_verifiers_);
-
     static const char kTestCert[] = "quic-chain.pem";
     test_cert_ = ImportCertFromFile(GetTestCertsDirectory(), kTestCert);
     ASSERT_TRUE(test_cert_);
@@ -238,8 +232,6 @@
   TransportSecurityState transport_security_state_;
   MockCTPolicyEnforcer ct_policy_enforcer_;
 
-  std::unique_ptr<MultiLogCTVerifier> ct_verifier_;
-  std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers_;
   std::unique_ptr<quic::ProofVerifyContext> verify_context_;
   std::unique_ptr<quic::ProofVerifyDetails> details_;
   std::string error_details_;
@@ -253,9 +245,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -288,9 +280,9 @@
 // verification fails.
 TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
   MockCertVerifier dummy_verifier;
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -320,12 +312,25 @@
   CertVerifyResult dummy_result;
   dummy_result.verified_cert = test_cert;
   dummy_result.is_issued_by_known_root = true;
-  MockCertVerifier dummy_verifier;
-  dummy_verifier.AddResultForCert(test_cert.get(), dummy_result, OK);
+  auto dummy_verifier = std::make_unique<MockCertVerifier>();
+  dummy_verifier->AddResultForCert(test_cert.get(), dummy_result, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  // Combine the mocked cert verify result with the results of the
+  // MultiLogCTVerifier.
+  std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers;
+  scoped_refptr<const CTLogVerifier> log(
+      CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
+  ASSERT_TRUE(log);
+  log_verifiers.push_back(log);
+  auto ct_verifier = std::make_unique<MultiLogCTVerifier>();
+  ct_verifier->AddLogs(log_verifiers);
+
+  CertAndCTVerifier cert_verifier(std::move(dummy_verifier),
+                                  std::move(ct_verifier));
+
+  ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -349,12 +354,25 @@
   CertVerifyResult dummy_result;
   dummy_result.verified_cert = test_cert;
   dummy_result.is_issued_by_known_root = true;
-  MockCertVerifier dummy_verifier;
-  dummy_verifier.AddResultForCert(test_cert.get(), dummy_result, OK);
+  auto dummy_verifier = std::make_unique<MockCertVerifier>();
+  dummy_verifier->AddResultForCert(test_cert.get(), dummy_result, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  // Combine the mocked cert verify result with the results of the
+  // MultiLogCTVerifier.
+  std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers;
+  scoped_refptr<const CTLogVerifier> log(
+      CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
+  ASSERT_TRUE(log);
+  log_verifiers.push_back(log);
+  auto ct_verifier = std::make_unique<MultiLogCTVerifier>();
+  ct_verifier->AddLogs(log_verifiers);
+
+  CertAndCTVerifier cert_verifier(std::move(dummy_verifier),
+                                  std::move(ct_verifier));
+
+  ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -370,9 +388,9 @@
 // signature fails.
 TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
   FailsTestCertVerifier cert_verifier;
-  ProofVerifierChromium proof_verifier(
-      &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -395,9 +413,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -439,9 +457,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -489,9 +507,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -546,9 +564,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -599,9 +617,9 @@
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
                                   ERR_CERT_DATE_INVALID);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -637,9 +655,9 @@
       base::Time::Now() + base::TimeDelta::FromSeconds(1000);
   transport_security_state_.AddHSTS(kTestHostname, expiry, true);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -673,9 +691,9 @@
   transport_security_state_.EnableStaticPinsForTesting();
   ScopedTransportSecurityStateSource scoped_security_state_source;
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -720,9 +738,9 @@
   transport_security_state_.EnableStaticPinsForTesting();
   ScopedTransportSecurityStateSource scoped_security_state_source;
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {kCTAndPKPHost}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr,
+                                       {kCTAndPKPHost}, NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -774,9 +792,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, network_isolation_key);
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       network_isolation_key);
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -835,9 +853,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -893,9 +911,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -951,7 +969,7 @@
     dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
     ProofVerifierChromium proof_verifier(
         &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-        ct_verifier_.get(), nullptr, {kTestHostname}, NetworkIsolationKey());
+        nullptr, {kTestHostname}, NetworkIsolationKey());
 
     std::unique_ptr<DummyProofVerifierCallback> callback(
         new DummyProofVerifierCallback);
@@ -975,9 +993,9 @@
     dummy_result_.is_issued_by_known_root = true;
     MockCertVerifier dummy_verifier;
     dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
-    ProofVerifierChromium proof_verifier(
-        &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-        ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+    ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                         &transport_security_state_, nullptr,
+                                         {}, NetworkIsolationKey());
 
     std::unique_ptr<DummyProofVerifierCallback> callback(
         new DummyProofVerifierCallback);
@@ -1019,9 +1037,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {kTestHostname}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr,
+                                       {kTestHostname}, NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -1066,9 +1084,9 @@
       .WillRepeatedly(
           Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -1120,7 +1138,7 @@
     dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
     ProofVerifierChromium proof_verifier(
         &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-        ct_verifier_.get(), nullptr, {kTestHostname}, NetworkIsolationKey());
+        nullptr, {kTestHostname}, NetworkIsolationKey());
 
     std::unique_ptr<DummyProofVerifierCallback> callback(
         new DummyProofVerifierCallback);
@@ -1146,9 +1164,9 @@
     dummy_result_.is_issued_by_known_root = true;
     MockCertVerifier dummy_verifier;
     dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
-    ProofVerifierChromium proof_verifier(
-        &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-        ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+    ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                         &transport_security_state_, nullptr,
+                                         {}, NetworkIsolationKey());
 
     std::unique_ptr<DummyProofVerifierCallback> callback(
         new DummyProofVerifierCallback);
@@ -1185,9 +1203,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr, {},
+                                       NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -1217,9 +1235,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {kTestHostname}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr,
+                                       {kTestHostname}, NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -1254,9 +1272,9 @@
   MockCertVerifier dummy_verifier;
   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
 
-  ProofVerifierChromium proof_verifier(
-      &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), nullptr, {""}, NetworkIsolationKey());
+  ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
+                                       &transport_security_state_, nullptr,
+                                       {""}, NetworkIsolationKey());
 
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
@@ -1306,7 +1324,7 @@
 
   ProofVerifierChromium proof_verifier(
       &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), &sct_auditing_delegate, {}, NetworkIsolationKey());
+      &sct_auditing_delegate, {}, NetworkIsolationKey());
 
   auto callback = std::make_unique<DummyProofVerifierCallback>();
   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
@@ -1323,42 +1341,5 @@
   ASSERT_EQ(quic::QUIC_SUCCESS, status);
 }
 
-// Tests that the SCTAuditingDelegate is not called when a cert isn't issued
-// from a known root. Mirrors `SCTAuditingReportCollected` test above, but with
-// `is_issued_by_known_root` set to false. Note that QUIC fails for certs that
-// aren't issued from known roots.
-TEST_F(ProofVerifierChromiumTest, SCTAuditingNonPublicCertsNotReported) {
-  MockCertVerifier cert_verifier;
-  dummy_result_.is_issued_by_known_root = false;
-  cert_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
-  EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
-      .WillRepeatedly(
-          Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
-  MockSCTAuditingDelegate sct_auditing_delegate;
-  EXPECT_CALL(sct_auditing_delegate, IsSCTAuditingEnabled())
-      .WillRepeatedly(Return(true));
-  HostPortPair host_port_pair(kTestHostname, kTestPort);
-  EXPECT_CALL(sct_auditing_delegate, MaybeEnqueueReport(host_port_pair, _, _))
-      .Times(0);
-
-  ProofVerifierChromium proof_verifier(
-      &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
-      ct_verifier_.get(), &sct_auditing_delegate, {}, NetworkIsolationKey());
-
-  auto callback = std::make_unique<DummyProofVerifierCallback>();
-  quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
-      kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
-      kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
-      verify_context_.get(), &error_details_, &details_, std::move(callback));
-  ASSERT_EQ(quic::QUIC_FAILURE, status);
-
-  callback = std::make_unique<DummyProofVerifierCallback>();
-  status = proof_verifier.VerifyCertChain(
-      kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
-      verify_context_.get(), &error_details_, &details_, &tls_alert_,
-      std::move(callback));
-  ASSERT_EQ(quic::QUIC_FAILURE, status);
-}
-
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/crypto_test_utils_chromium.cc b/net/quic/crypto_test_utils_chromium.cc
index 761c029..a3bfad3e 100644
--- a/net/quic/crypto_test_utils_chromium.cc
+++ b/net/quic/crypto_test_utils_chromium.cc
@@ -47,19 +47,16 @@
   TestProofVerifierChromium(
       std::unique_ptr<CertVerifier> cert_verifier,
       std::unique_ptr<TransportSecurityState> transport_security_state,
-      std::unique_ptr<CTVerifier> cert_transparency_verifier,
       std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer,
       const std::string& cert_file)
       : ProofVerifierChromium(cert_verifier.get(),
                               ct_policy_enforcer.get(),
                               transport_security_state.get(),
-                              cert_transparency_verifier.get(),
                               /*sct_auditing_delegate=*/nullptr,
                               {"test.example.com"},
                               NetworkIsolationKey()),
         cert_verifier_(std::move(cert_verifier)),
         transport_security_state_(std::move(transport_security_state)),
-        cert_transparency_verifier_(std::move(cert_transparency_verifier)),
         ct_policy_enforcer_(std::move(ct_policy_enforcer)) {
     // Load and install the root for the validated chain.
     scoped_refptr<X509Certificate> root_cert =
@@ -75,7 +72,6 @@
   ScopedTestRoot scoped_root_;
   std::unique_ptr<CertVerifier> cert_verifier_;
   std::unique_ptr<TransportSecurityState> transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_;
 };
 
@@ -110,7 +106,6 @@
                                          net::OK);
   return std::make_unique<net::test::TestProofVerifierChromium>(
       std::move(cert_verifier), std::make_unique<net::TransportSecurityState>(),
-      std::make_unique<net::MultiLogCTVerifier>(),
       std::make_unique<net::DefaultCTPolicyEnforcer>(), "quic-root.pem");
 }
 
diff --git a/net/quic/platform/impl/quic_default_proof_providers_impl.cc b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
index abae462..f7ea1ed 100644
--- a/net/quic/platform/impl/quic_default_proof_providers_impl.cc
+++ b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
@@ -13,7 +13,6 @@
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_log_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/http/transport_security_state.h"
 #include "net/quic/crypto/proof_source_chromium.h"
 #include "net/quic/crypto/proof_verifier_chromium.h"
@@ -39,8 +38,6 @@
                               "Path to the pkcs8 private key.");
 
 using net::CertVerifier;
-using net::CTVerifier;
-using net::MultiLogCTVerifier;
 using net::ProofVerifierChromium;
 
 namespace quic {
@@ -64,7 +61,6 @@
       : net::ProofVerifierChromium(cert_verifier.get(),
                                    &ct_policy_enforcer_,
                                    &transport_security_state_,
-                                   &ct_verifier_,
                                    /*sct_auditing_delegate=*/nullptr,
                                    UnknownRootAllowlistForHost(host),
                                    // Fine to use an empty NetworkIsolationKey
@@ -76,7 +72,6 @@
   std::unique_ptr<net::CertVerifier> cert_verifier_;
   net::DefaultCTPolicyEnforcer ct_policy_enforcer_;
   net::TransportSecurityState transport_security_state_;
-  net::MultiLogCTVerifier ct_verifier_;
 };
 
 std::unique_ptr<ProofVerifier> CreateDefaultProofVerifierImpl(
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 57100d9..c440ae8 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -2213,7 +2213,8 @@
   connection()->SetSelfAddress(self_address);
 
   // Close streams that are not migratable to the probed |network|.
-  ResetNonMigratableStreams();
+  if (!allow_port_migration_)
+    ResetNonMigratableStreams();
 
   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
     // If idle sessions won't be migrated, close the connection.
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc
index ce28ee63..1c4532e 100644
--- a/net/quic/quic_end_to_end_unittest.cc
+++ b/net/quic/quic_end_to_end_unittest.cc
@@ -88,7 +88,6 @@
   QuicEndToEndTest()
       : host_resolver_impl_(CreateResolverImpl()),
         host_resolver_(std::move(host_resolver_impl_)),
-        cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
         proxy_resolution_service_(
             ConfiguredProxyResolutionService::CreateDirect()),
@@ -106,8 +105,6 @@
     session_context_.host_resolver = &host_resolver_;
     session_context_.cert_verifier = &cert_verifier_;
     session_context_.transport_security_state = &transport_security_state_;
-    session_context_.cert_transparency_verifier =
-        cert_transparency_verifier_.get();
     session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context_.proxy_resolution_service = proxy_resolution_service_.get();
     session_context_.ssl_config_service = ssl_config_service_.get();
@@ -218,7 +215,6 @@
   MappedHostResolver host_resolver_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 3776bdbe..2eade5e 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -30,7 +30,6 @@
 #include "net/base/test_proxy_delegate.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_network_session.h"
@@ -317,7 +316,6 @@
                       quic::Perspective::IS_SERVER,
                       false),
         quic_task_runner_(new TestTaskRunner(context_.mock_clock())),
-        cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
         proxy_resolution_service_(
             ConfiguredProxyResolutionService::CreateDirect()),
@@ -642,8 +640,6 @@
     session_context_.host_resolver = &host_resolver_;
     session_context_.cert_verifier = &cert_verifier_;
     session_context_.transport_security_state = &transport_security_state_;
-    session_context_.cert_transparency_verifier =
-        cert_transparency_verifier_.get();
     session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context_.socket_performance_watcher_factory =
         &test_socket_performance_watcher_factory_;
@@ -980,7 +976,6 @@
   MockHostResolver host_resolver_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_;
   std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
@@ -7049,7 +7044,6 @@
             GetParam().client_headers_include_h2_stream_dependency),
         supported_versions_(quic::test::SupportedVersions(version_)),
         destination_type_(GetParam().destination_type),
-        cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
         proxy_resolution_service_(
             ConfiguredProxyResolutionService::CreateDirect()),
@@ -7083,8 +7077,6 @@
     session_context.host_resolver = &host_resolver_;
     session_context.cert_verifier = &cert_verifier_;
     session_context.transport_security_state = &transport_security_state_;
-    session_context.cert_transparency_verifier =
-        cert_transparency_verifier_.get();
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context.socket_performance_watcher_factory =
         &test_socket_performance_watcher_factory_;
@@ -7261,7 +7253,6 @@
   MockHostResolver host_resolver_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_;
   std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index bb888cf..78f8a826 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -32,7 +32,6 @@
 #include "net/base/net_errors.h"
 #include "net/base/trace_constants.h"
 #include "net/cert/cert_verifier.h"
-#include "net/cert/ct_verifier.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/public/secure_dns_mode.h"
 #include "net/log/net_log.h"
@@ -1068,7 +1067,6 @@
     CertVerifier* cert_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
     TransportSecurityState* transport_security_state,
-    CTVerifier* cert_transparency_verifier,
     SCTAuditingDelegate* sct_auditing_delegate,
     SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
     QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
@@ -1082,7 +1080,6 @@
       cert_verifier_(cert_verifier),
       ct_policy_enforcer_(ct_policy_enforcer),
       transport_security_state_(transport_security_state),
-      cert_transparency_verifier_(cert_transparency_verifier),
       sct_auditing_delegate_(sct_auditing_delegate),
       quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
       random_generator_(quic_context->random_generator()),
@@ -2143,7 +2140,7 @@
       std::make_unique<QuicCryptoClientConfigOwner>(
           std::make_unique<ProofVerifierChromium>(
               cert_verifier_, ct_policy_enforcer_, transport_security_state_,
-              cert_transparency_verifier_, sct_auditing_delegate_,
+              sct_auditing_delegate_,
               HostsFromOrigins(params_.origins_to_force_quic_on),
               actual_network_isolation_key),
           std::make_unique<QuicClientSessionCache>(), this);
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 95237cb..da3ba3b 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -64,7 +64,6 @@
 class CTPolicyEnforcer;
 class CertVerifier;
 class ClientSocketFactory;
-class CTVerifier;
 class HostResolver;
 class HttpServerProperties;
 class NetLog;
@@ -242,7 +241,6 @@
       CertVerifier* cert_verifier,
       CTPolicyEnforcer* ct_policy_enforcer,
       TransportSecurityState* transport_security_state,
-      CTVerifier* cert_transparency_verifier,
       SCTAuditingDelegate* sct_auditing_delegate,
       SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
       QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
@@ -500,7 +498,6 @@
   CertVerifier* const cert_verifier_;
   CTPolicyEnforcer* const ct_policy_enforcer_;
   TransportSecurityState* const transport_security_state_;
-  CTVerifier* const cert_transparency_verifier_;
   SCTAuditingDelegate* const sct_auditing_delegate_;
   QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
   quic::QuicRandom* random_generator_;  // Unowned.
diff --git a/net/quic/quic_stream_factory_fuzzer.cc b/net/quic/quic_stream_factory_fuzzer.cc
index 6236dc6..0b9b8ab3 100644
--- a/net/quic/quic_stream_factory_fuzzer.cc
+++ b/net/quic/quic_stream_factory_fuzzer.cc
@@ -57,7 +57,6 @@
     ssl_config_service = std::make_unique<SSLConfigServiceDefaults>();
     crypto_client_stream_factory.set_use_mock_crypter(true);
     cert_verifier = std::make_unique<MockCertVerifier>();
-    cert_transparency_verifier = std::make_unique<DoNothingCTVerifier>();
     verify_details.cert_verify_result.verified_cert =
         X509Certificate::CreateFromBytes(kCertData, base::size(kCertData));
     CHECK(verify_details.cert_verify_result.verified_cert);
@@ -73,7 +72,6 @@
   TransportSecurityState transport_security_state;
   quic::QuicTagVector connection_options;
   quic::QuicTagVector client_connection_options;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier;
   DefaultCTPolicyEnforcer ct_policy_enforcer;
   MockQuicContext quic_context;
 };
@@ -134,9 +132,8 @@
           env->net_log.net_log(), host_resolver.get(),
           env->ssl_config_service.get(), &socket_factory,
           &http_server_properties, env->cert_verifier.get(),
-          &env->ct_policy_enforcer, &env->transport_security_state,
-          env->cert_transparency_verifier.get(), nullptr, nullptr,
-          &env->crypto_client_stream_factory, &env->quic_context);
+          &env->ct_policy_enforcer, &env->transport_security_state, nullptr,
+          nullptr, &env->crypto_client_stream_factory, &env->quic_context);
 
   QuicStreamRequest request(factory.get());
   TestCompletionCallback callback;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 7839158..469d132 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -26,7 +26,6 @@
 #include "net/base/network_isolation_key.h"
 #include "net/base/schemeful_site.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/do_nothing_ct_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/dns/host_resolver_source.h"
 #include "net/dns/mock_host_resolver.h"
@@ -73,6 +72,7 @@
 #include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
 #include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
 #include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
@@ -238,7 +238,6 @@
                       false),
         http_server_properties_(std::make_unique<HttpServerProperties>()),
         cert_verifier_(std::make_unique<MockCertVerifier>()),
-        cert_transparency_verifier_(std::make_unique<DoNothingCTVerifier>()),
         scoped_mock_network_change_notifier_(nullptr),
         factory_(nullptr),
         host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
@@ -264,7 +263,7 @@
         net_log_.net_log(), host_resolver_.get(), ssl_config_service_.get(),
         socket_factory_.get(), http_server_properties_.get(),
         cert_verifier_.get(), &ct_policy_enforcer_, &transport_security_state_,
-        cert_transparency_verifier_.get(), /*sct_auditing_delegate=*/nullptr,
+        /*sct_auditing_delegate=*/nullptr,
         /*SocketPerformanceWatcherFactory*/ nullptr,
         &crypto_client_stream_factory_, &context_);
   }
@@ -914,7 +913,6 @@
   std::unique_ptr<HttpServerProperties> http_server_properties_;
   std::unique_ptr<CertVerifier> cert_verifier_;
   TransportSecurityState transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   std::unique_ptr<ScopedMockNetworkChangeNotifier>
       scoped_mock_network_change_notifier_;
@@ -4669,6 +4667,14 @@
   HttpRequestHeaders request_headers;
   EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
                                     callback_.callback()));
+  // Disable connection migration on the request streams.
+  // This should have no effect for port migration.
+  QuicChromiumClientStream* chrome_stream =
+      static_cast<QuicChromiumClientStream*>(
+          quic::test::QuicSessionPeer::GetStream(
+              session, GetNthClientInitiatedBidirectionalStreamId(0)));
+  EXPECT_TRUE(chrome_stream);
+  chrome_stream->DisableConnectionMigrationToCellularNetwork();
 
   EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
 
@@ -4725,9 +4731,14 @@
 
   EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
 
-  // Verify that the session is still alive.
+  // Verify that the session is still alive, and the request stream is still
+  // alive.
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  chrome_stream = static_cast<QuicChromiumClientStream*>(
+      quic::test::QuicSessionPeer::GetStream(
+          session, GetNthClientInitiatedBidirectionalStreamId(0)));
+  EXPECT_TRUE(chrome_stream);
 
   stream.reset();
   EXPECT_TRUE(quic_data1.AllReadDataConsumed());
diff --git a/net/quic/quic_transport_client.cc b/net/quic/quic_transport_client.cc
index 09ed5db8..26537532 100644
--- a/net/quic/quic_transport_client.cc
+++ b/net/quic/quic_transport_client.cc
@@ -39,8 +39,7 @@
   if (parameters.server_certificate_fingerprints.empty()) {
     return std::make_unique<ProofVerifierChromium>(
         context->cert_verifier(), context->ct_policy_enforcer(),
-        context->transport_security_state(),
-        context->cert_transparency_verifier(), context->sct_auditing_delegate(),
+        context->transport_security_state(), context->sct_auditing_delegate(),
         HostsFromOrigins(
             context->quic_context()->params()->origins_to_force_quic_on),
         isolation_key);
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index 4d136f7..fcfc88b 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -50,20 +50,17 @@
     SSLConfigService* ssl_config_service,
     CertVerifier* cert_verifier,
     TransportSecurityState* transport_security_state,
-    CTVerifier* cert_transparency_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
     SSLClientSessionCache* ssl_client_session_cache,
     SCTAuditingDelegate* sct_auditing_delegate)
     : ssl_config_service_(ssl_config_service),
       cert_verifier_(cert_verifier),
       transport_security_state_(transport_security_state),
-      cert_transparency_verifier_(cert_transparency_verifier),
       ct_policy_enforcer_(ct_policy_enforcer),
       ssl_client_session_cache_(ssl_client_session_cache),
       sct_auditing_delegate_(sct_auditing_delegate) {
   CHECK(cert_verifier_);
   CHECK(transport_security_state_);
-  CHECK(cert_transparency_verifier_);
   CHECK(ct_policy_enforcer_);
 
   if (ssl_config_service_) {
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index 6b9aeb32..0f0fe9a3 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -23,7 +23,6 @@
 
 class CTPolicyEnforcer;
 class CertVerifier;
-class CTVerifier;
 class HostPortPair;
 class SCTAuditingDelegate;
 class SSLClientSessionCache;
@@ -103,7 +102,6 @@
   SSLClientContext(SSLConfigService* ssl_config_service,
                    CertVerifier* cert_verifier,
                    TransportSecurityState* transport_security_state,
-                   CTVerifier* cert_transparency_verifier,
                    CTPolicyEnforcer* ct_policy_enforcer,
                    SSLClientSessionCache* ssl_client_session_cache,
                    SCTAuditingDelegate* sct_auditing_delegate);
@@ -116,9 +114,6 @@
   TransportSecurityState* transport_security_state() {
     return transport_security_state_;
   }
-  CTVerifier* cert_transparency_verifier() {
-    return cert_transparency_verifier_;
-  }
   CTPolicyEnforcer* ct_policy_enforcer() { return ct_policy_enforcer_; }
   SSLClientSessionCache* ssl_client_session_cache() {
     return ssl_client_session_cache_;
@@ -186,7 +181,6 @@
   SSLConfigService* ssl_config_service_;
   CertVerifier* cert_verifier_;
   TransportSecurityState* transport_security_state_;
-  CTVerifier* cert_transparency_verifier_;
   CTPolicyEnforcer* ct_policy_enforcer_;
   SSLClientSessionCache* ssl_client_session_cache_;
   SCTAuditingDelegate* sct_auditing_delegate_;
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index d29204c..bd39afc 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -1197,7 +1197,7 @@
   // If the connection was good, check HPKP and CT status simultaneously,
   // but prefer to treat the HPKP error as more serious, if there was one.
   if (result == OK) {
-    int ct_result = VerifyCT();
+    int ct_result = CheckCTCompliance();
     TransportSecurityState::PKPStatus pin_validity =
         context_->transport_security_state()->CheckPublicKeyPins(
             host_and_port_, server_cert_verify_result_.is_issued_by_known_root,
@@ -1255,6 +1255,89 @@
   return ssl_verify_invalid;
 }
 
+int SSLClientSocketImpl::CheckCTCompliance() {
+  ct::SCTList verified_scts;
+  for (const auto& sct_and_status : server_cert_verify_result_.scts) {
+    if (sct_and_status.status == ct::SCT_STATUS_OK)
+      verified_scts.push_back(sct_and_status.sct);
+  }
+  server_cert_verify_result_.policy_compliance =
+      context_->ct_policy_enforcer()->CheckCompliance(
+          server_cert_verify_result_.verified_cert.get(), verified_scts,
+          net_log_);
+  if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
+    if (server_cert_verify_result_.policy_compliance !=
+            ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
+        server_cert_verify_result_.policy_compliance !=
+            ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
+      server_cert_verify_result_.cert_status |=
+          CERT_STATUS_CT_COMPLIANCE_FAILED;
+      server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
+    }
+
+    // Record the CT compliance status for connections with EV certificates,
+    // to distinguish how often EV status is being dropped due to failing CT
+    // compliance.
+    if (server_cert_verify_result_.is_issued_by_known_root) {
+      UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.EVCompliance2.SSL",
+                                server_cert_verify_result_.policy_compliance,
+                                ct::CTPolicyCompliance::CT_POLICY_COUNT);
+    }
+  }
+
+  // Record the CT compliance of every connection to get an overall picture of
+  // how many connections are CT-compliant.
+  if (server_cert_verify_result_.is_issued_by_known_root) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Net.CertificateTransparency.ConnectionComplianceStatus2.SSL",
+        server_cert_verify_result_.policy_compliance,
+        ct::CTPolicyCompliance::CT_POLICY_COUNT);
+  }
+
+  TransportSecurityState::CTRequirementsStatus ct_requirement_status =
+      context_->transport_security_state()->CheckCTRequirements(
+          host_and_port_, server_cert_verify_result_.is_issued_by_known_root,
+          server_cert_verify_result_.public_key_hashes,
+          server_cert_verify_result_.verified_cert.get(), server_cert_.get(),
+          server_cert_verify_result_.scts,
+          TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+          server_cert_verify_result_.policy_compliance,
+          ssl_config_.network_isolation_key);
+  if (ct_requirement_status != TransportSecurityState::CT_NOT_REQUIRED) {
+    if (server_cert_verify_result_.is_issued_by_known_root) {
+      // Record the CT compliance of connections for which compliance is
+      // required; this helps answer the question: "Of all connections that
+      // are supposed to be serving valid CT information, how many fail to do
+      // so?"
+      UMA_HISTOGRAM_ENUMERATION(
+          "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2."
+          "SSL",
+          server_cert_verify_result_.policy_compliance,
+          ct::CTPolicyCompliance::CT_POLICY_COUNT);
+    }
+  }
+
+  if (context_->sct_auditing_delegate() &&
+      context_->sct_auditing_delegate()->IsSCTAuditingEnabled()) {
+    context_->sct_auditing_delegate()->MaybeEnqueueReport(
+        host_and_port_, server_cert_verify_result_.verified_cert.get(),
+        server_cert_verify_result_.scts);
+  }
+
+  switch (ct_requirement_status) {
+    case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
+      server_cert_verify_result_.cert_status |=
+          CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
+      return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
+    case TransportSecurityState::CT_REQUIREMENTS_MET:
+    case TransportSecurityState::CT_NOT_REQUIRED:
+      return OK;
+  }
+
+  NOTREACHED();
+  return OK;
+}
+
 void SSLClientSocketImpl::DoConnectCallback(int rv) {
   if (!user_connect_callback_.is_null()) {
     std::move(user_connect_callback_).Run(rv > OK ? OK : rv);
@@ -1527,108 +1610,6 @@
     DoWriteCallback(rv_write);
 }
 
-int SSLClientSocketImpl::VerifyCT() {
-  const uint8_t* sct_list_raw;
-  size_t sct_list_len;
-  SSL_get0_signed_cert_timestamp_list(ssl_.get(), &sct_list_raw, &sct_list_len);
-  base::StringPiece sct_list(reinterpret_cast<const char*>(sct_list_raw),
-                             sct_list_len);
-
-  const uint8_t* ocsp_response_raw;
-  size_t ocsp_response_len;
-  SSL_get0_ocsp_response(ssl_.get(), &ocsp_response_raw, &ocsp_response_len);
-  base::StringPiece ocsp_response(
-      reinterpret_cast<const char*>(ocsp_response_raw), ocsp_response_len);
-
-  // Note that this is a completely synchronous operation: The CT Log Verifier
-  // gets all the data it needs for SCT verification and does not do any
-  // external communication.
-  context_->cert_transparency_verifier()->Verify(
-      host_and_port().host(), server_cert_verify_result_.verified_cert.get(),
-      ocsp_response, sct_list, &server_cert_verify_result_.scts, net_log_);
-
-  ct::SCTList verified_scts;
-  for (const auto& sct_and_status : server_cert_verify_result_.scts) {
-    if (sct_and_status.status == ct::SCT_STATUS_OK)
-      verified_scts.push_back(sct_and_status.sct);
-  }
-  server_cert_verify_result_.policy_compliance =
-      context_->ct_policy_enforcer()->CheckCompliance(
-          server_cert_verify_result_.verified_cert.get(), verified_scts,
-          net_log_);
-  if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) {
-    if (server_cert_verify_result_.policy_compliance !=
-            ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
-        server_cert_verify_result_.policy_compliance !=
-            ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
-      server_cert_verify_result_.cert_status |=
-          CERT_STATUS_CT_COMPLIANCE_FAILED;
-      server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
-    }
-
-    // Record the CT compliance status for connections with EV certificates, to
-    // distinguish how often EV status is being dropped due to failing CT
-    // compliance.
-    if (server_cert_verify_result_.is_issued_by_known_root) {
-      UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.EVCompliance2.SSL",
-                                server_cert_verify_result_.policy_compliance,
-                                ct::CTPolicyCompliance::CT_POLICY_COUNT);
-    }
-  }
-
-  // Record the CT compliance of every connection to get an overall picture of
-  // how many connections are CT-compliant.
-  if (server_cert_verify_result_.is_issued_by_known_root) {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Net.CertificateTransparency.ConnectionComplianceStatus2.SSL",
-        server_cert_verify_result_.policy_compliance,
-        ct::CTPolicyCompliance::CT_POLICY_COUNT);
-  }
-
-  TransportSecurityState::CTRequirementsStatus ct_requirement_status =
-      context_->transport_security_state()->CheckCTRequirements(
-          host_and_port_, server_cert_verify_result_.is_issued_by_known_root,
-          server_cert_verify_result_.public_key_hashes,
-          server_cert_verify_result_.verified_cert.get(), server_cert_.get(),
-          server_cert_verify_result_.scts,
-          TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
-          server_cert_verify_result_.policy_compliance,
-          ssl_config_.network_isolation_key);
-  if (ct_requirement_status != TransportSecurityState::CT_NOT_REQUIRED) {
-    if (server_cert_verify_result_.is_issued_by_known_root) {
-      // Record the CT compliance of connections for which compliance is
-      // required; this helps answer the question: "Of all connections that are
-      // supposed to be serving valid CT information, how many fail to do so?"
-      UMA_HISTOGRAM_ENUMERATION(
-          "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2."
-          "SSL",
-          server_cert_verify_result_.policy_compliance,
-          ct::CTPolicyCompliance::CT_POLICY_COUNT);
-    }
-  }
-
-  if (context_->sct_auditing_delegate() &&
-      context_->sct_auditing_delegate()->IsSCTAuditingEnabled() &&
-      server_cert_verify_result_.is_issued_by_known_root) {
-    context_->sct_auditing_delegate()->MaybeEnqueueReport(
-        host_and_port_, server_cert_verify_result_.verified_cert.get(),
-        server_cert_verify_result_.scts);
-  }
-
-  switch (ct_requirement_status) {
-    case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
-      server_cert_verify_result_.cert_status |=
-          CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
-      return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
-    case TransportSecurityState::CT_REQUIREMENTS_MET:
-    case TransportSecurityState::CT_NOT_REQUIRED:
-      return OK;
-  }
-
-  NOTREACHED();
-  return OK;
-}
-
 int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
   DCHECK(ssl == ssl_.get());
 
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h
index d0113326..31a2e66 100644
--- a/net/socket/ssl_client_socket_impl.h
+++ b/net/socket/ssl_client_socket_impl.h
@@ -148,7 +148,7 @@
   static ssl_verify_result_t VerifyCertCallback(SSL* ssl, uint8_t* out_alert);
   ssl_verify_result_t VerifyCert();
   ssl_verify_result_t HandleVerifyResult();
-  int VerifyCT();
+  int CheckCTCompliance();
 
   // Callback from the SSL layer that indicates the remote server is requesting
   // a certificate for this client.
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index a1f5b51..7792005 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -40,6 +40,7 @@
 #include "net/base/schemeful_site.h"
 #include "net/base/test_completion_callback.h"
 #include "net/cert/asn1_util.h"
+#include "net/cert/cert_and_ct_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/ct_policy_status.h"
 #include "net/cert/ct_verifier.h"
@@ -707,7 +708,6 @@
             std::make_unique<TestSSLConfigService>(SSLContextConfig())),
         cert_verifier_(std::make_unique<MockCertVerifier>()),
         transport_security_state_(std::make_unique<TransportSecurityState>()),
-        ct_verifier_(std::make_unique<DoNothingCTVerifier>()),
         ct_policy_enforcer_(std::make_unique<MockCTPolicyEnforcer>()),
         ssl_client_session_cache_(std::make_unique<SSLClientSessionCache>(
             SSLClientSessionCache::Config())),
@@ -715,7 +715,6 @@
             std::make_unique<SSLClientContext>(ssl_config_service_.get(),
                                                cert_verifier_.get(),
                                                transport_security_state_.get(),
-                                               ct_verifier_.get(),
                                                ct_policy_enforcer_.get(),
                                                ssl_client_session_cache_.get(),
                                                nullptr)) {
@@ -880,7 +879,6 @@
   std::unique_ptr<TestSSLConfigService> ssl_config_service_;
   std::unique_ptr<MockCertVerifier> cert_verifier_;
   std::unique_ptr<TransportSecurityState> transport_security_state_;
-  std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
   std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
   std::unique_ptr<SSLClientSessionCache> ssl_client_session_cache_;
   std::unique_ptr<SSLClientContext> context_;
@@ -1541,8 +1539,7 @@
   HangingCertVerifier verifier;
   context_ = std::make_unique<SSLClientContext>(
       ssl_config_service_.get(), &verifier, transport_security_state_.get(),
-      ct_verifier_.get(), ct_policy_enforcer_.get(),
-      ssl_client_session_cache_.get(), nullptr);
+      ct_policy_enforcer_.get(), ssl_client_session_cache_.get(), nullptr);
 
   TestCompletionCallback callback;
   auto transport = std::make_unique<TCPClientSocket>(addr(), nullptr, nullptr,
@@ -2786,18 +2783,22 @@
   ssl_options.signed_cert_timestamps_tls_ext = sct_ext.as_string();
   ASSERT_TRUE(StartTestServer(ssl_options));
 
-  MockCTVerifier ct_verifier;
-  context_ = std::make_unique<SSLClientContext>(
-      ssl_config_service_.get(), cert_verifier_.get(),
-      transport_security_state_.get(), &ct_verifier, ct_policy_enforcer_.get(),
-      ssl_client_session_cache_.get(), nullptr);
+  auto ct_verifier = std::make_unique<MockCTVerifier>();
 
   // Check that the SCT list is extracted from the TLS extension as expected,
   // while also simulating that it was an unparsable response.
   SignedCertificateTimestampAndStatusList sct_list;
-  EXPECT_CALL(ct_verifier, Verify(_, _, _, sct_ext, _, _))
+  EXPECT_CALL(*ct_verifier, Verify(_, _, _, sct_ext, _, _))
       .WillOnce(testing::SetArgPointee<4>(sct_list));
 
+  auto cert_and_ct_verifier = std::make_unique<CertAndCTVerifier>(
+      std::move(cert_verifier_), std::move(ct_verifier));
+
+  context_ = std::make_unique<SSLClientContext>(
+      ssl_config_service_.get(), cert_and_ct_verifier.get(),
+      transport_security_state_.get(), ct_policy_enforcer_.get(),
+      ssl_client_session_cache_.get(), nullptr);
+
   int rv;
   ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
   EXPECT_THAT(rv, IsOk());
@@ -4543,9 +4544,8 @@
   MockSCTAuditingDelegate sct_auditing_delegate;
   context_ = std::make_unique<SSLClientContext>(
       ssl_config_service_.get(), cert_verifier_.get(),
-      transport_security_state_.get(), ct_verifier_.get(),
-      ct_policy_enforcer_.get(), ssl_client_session_cache_.get(),
-      &sct_auditing_delegate);
+      transport_security_state_.get(), ct_policy_enforcer_.get(),
+      ssl_client_session_cache_.get(), &sct_auditing_delegate);
 
   EXPECT_CALL(sct_auditing_delegate, IsSCTAuditingEnabled())
       .WillRepeatedly(Return(true));
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc
index 94932d4..9ef6e6e 100644
--- a/net/socket/ssl_connect_job_unittest.cc
+++ b/net/socket/ssl_connect_job_unittest.cc
@@ -23,7 +23,6 @@
 #include "net/base/network_isolation_key.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_log_ct_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/dns/public/secure_dns_mode.h"
 #include "net/http/http_auth_handler_factory.h"
@@ -154,7 +153,6 @@
     session_context.host_resolver = &host_resolver_;
     session_context.cert_verifier = &cert_verifier_;
     session_context.transport_security_state = &transport_security_state_;
-    session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.client_socket_factory = &socket_factory_;
@@ -172,7 +170,6 @@
   MockHostResolver host_resolver_;
   MockCertVerifier cert_verifier_;
   TransportSecurityState transport_security_state_;
-  MultiLogCTVerifier ct_verifier_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   const std::unique_ptr<SSLConfigService> ssl_config_service_;
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 90591916..327b64f 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -47,7 +47,6 @@
 #include "net/cert/cert_status_flags.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/ct_policy_status.h"
-#include "net/cert/do_nothing_ct_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/cert/mock_client_cert_verifier.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
@@ -358,7 +357,6 @@
         cert_verifier_(new MockCertVerifier()),
         client_cert_verifier_(new MockClientCertVerifier()),
         transport_security_state_(new TransportSecurityState),
-        ct_verifier_(new DoNothingCTVerifier),
         ct_policy_enforcer_(new MockCTPolicyEnforcer),
         ssl_client_session_cache_(
             new SSLClientSessionCache(SSLClientSessionCache::Config())) {}
@@ -386,8 +384,8 @@
 
     client_context_ = std::make_unique<SSLClientContext>(
         ssl_config_service_.get(), cert_verifier_.get(),
-        transport_security_state_.get(), ct_verifier_.get(),
-        ct_policy_enforcer_.get(), ssl_client_session_cache_.get(), nullptr);
+        transport_security_state_.get(), ct_policy_enforcer_.get(),
+        ssl_client_session_cache_.get(), nullptr);
   }
 
  protected:
@@ -513,7 +511,6 @@
   std::unique_ptr<MockCertVerifier> cert_verifier_;
   std::unique_ptr<MockClientCertVerifier> client_cert_verifier_;
   std::unique_ptr<TransportSecurityState> transport_security_state_;
-  std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
   std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
   std::unique_ptr<SSLClientSessionCache> ssl_client_session_cache_;
   std::unique_ptr<SSLClientContext> client_context_;
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index eed8657..37d4570 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -94,7 +94,9 @@
 
 }  // anonymous namespace
 
-const size_t SpdyHttpStream::kRequestBodyBufferSize = 1 << 14;  // 16KB
+// Align our request body with |kMaxSpdyFrameChunkSize| to prevent unexpected
+// buffer chunking. This is 16KB - frame header size.
+const size_t SpdyHttpStream::kRequestBodyBufferSize = kMaxSpdyFrameChunkSize;
 
 SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
                                spdy::SpdyStreamId pushed_stream_id,
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index f32dd92..4f336d9 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -7509,14 +7509,12 @@
   writes.push_back(CreateMockWrite(req, i++));
   for (size_t j = 0; j < num_upload_buffers; j++) {
     for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
-      if (k == num_frames_in_one_upload_buffer - 1 &&
-          kBufferSize % kMaxSpdyFrameChunkSize != 0) {
-        if (j == num_upload_buffers - 1 &&
-            (initial_window_size % kBufferSize != 0)) {
-          writes.push_back(CreateMockWrite(body3, i++));
-        } else {
-          writes.push_back(CreateMockWrite(body2, i++));
-        }
+      if (j == num_upload_buffers - 1 &&
+          (initial_window_size % kBufferSize != 0)) {
+        writes.push_back(CreateMockWrite(body3, i++));
+      } else if (k == num_frames_in_one_upload_buffer - 1 &&
+                 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
+        writes.push_back(CreateMockWrite(body2, i++));
       } else {
         writes.push_back(CreateMockWrite(body1, i++));
       }
@@ -7660,14 +7658,12 @@
   writes.push_back(CreateMockWrite(req, i++));
   for (size_t j = 0; j < num_upload_buffers; j++) {
     for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
-      if (k == num_frames_in_one_upload_buffer - 1 &&
-          kBufferSize % kMaxSpdyFrameChunkSize != 0) {
-        if (j == num_upload_buffers - 1 &&
-            (initial_window_size % kBufferSize != 0)) {
-          writes.push_back(CreateMockWrite(body3, i++));
-        } else {
-          writes.push_back(CreateMockWrite(body2, i++));
-        }
+      if (j == num_upload_buffers - 1 &&
+          (initial_window_size % kBufferSize != 0)) {
+        writes.push_back(CreateMockWrite(body3, i++));
+      } else if (k == num_frames_in_one_upload_buffer - 1 &&
+                 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
+        writes.push_back(CreateMockWrite(body2, i++));
       } else {
         writes.push_back(CreateMockWrite(body1, i++));
       }
@@ -7823,14 +7819,12 @@
   writes.push_back(CreateMockWrite(req, i++));
   for (size_t j = 0; j < num_upload_buffers; j++) {
     for (size_t k = 0; k < num_frames_in_one_upload_buffer; k++) {
-      if (k == num_frames_in_one_upload_buffer - 1 &&
-          kBufferSize % kMaxSpdyFrameChunkSize != 0) {
-        if (j == num_upload_buffers - 1 &&
-            (initial_window_size % kBufferSize != 0)) {
-          writes.push_back(CreateMockWrite(body3, i++));
-        } else {
-          writes.push_back(CreateMockWrite(body2, i++));
-        }
+      if (j == num_upload_buffers - 1 &&
+          (initial_window_size % kBufferSize != 0)) {
+        writes.push_back(CreateMockWrite(body3, i++));
+      } else if (k == num_frames_in_one_upload_buffer - 1 &&
+                 kBufferSize % kMaxSpdyFrameChunkSize != 0) {
+        writes.push_back(CreateMockWrite(body2, i++));
       } else {
         writes.push_back(CreateMockWrite(body1, i++));
       }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index a0aa330..206ce41 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -60,13 +60,14 @@
 class SpdyStreamTest;
 }
 
-// This is somewhat arbitrary and not really fixed, but it will always work
-// reasonably with ethernet. Chop the world into 2-packet chunks.  This is
-// somewhat arbitrary, but is reasonably small and ensures that we elicit
-// ACKs quickly from TCP (because TCP tries to only ACK every other packet).
-const int kMss = 1430;
-// The 8 is the size of the SPDY frame header.
-const int kMaxSpdyFrameChunkSize = (2 * kMss) - 8;
+// TLS and other layers will chunk data at 16KB. Making the max frame size too
+// small will lead to increased CPU/byte cost and overhead on both client/server
+// due to excessive frames to process. Making this larger has diminishing
+// returns as the data will be chunked elsewhere. We also want to ensure we are
+// >= 2860B (~2* MSS => 2 packets) to avoid delayed ACKs. We will also account
+// for the frame header size of 9B to prevent fragmentation when this is added.
+// As a result we will use a 16KB - 9B max data frame size.
+const int kMaxSpdyFrameChunkSize = (16 * 1024) - 9;
 
 // Default value of spdy::SETTINGS_INITIAL_WINDOW_SIZE per protocol
 // specification. A session is always created with this initial window size.
@@ -365,9 +366,7 @@
   const HostPortProxyPair& host_port_proxy_pair() const {
     return spdy_session_key_.host_port_proxy_pair();
   }
-  const SpdySessionKey& spdy_session_key() const {
-    return spdy_session_key_;
-  }
+  const SpdySessionKey& spdy_session_key() const { return spdy_session_key_; }
 
   // Get a pushed stream for a given |url| with stream ID |pushed_stream_id|.
   // The caller must have already claimed the stream from Http2PushPromiseIndex.
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index a663494..8f846a38 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -19,7 +19,6 @@
 #include "net/base/http_user_agent_settings.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/ct_policy_status.h"
-#include "net/cert/do_nothing_ct_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 #include "net/dns/host_resolver.h"
@@ -328,7 +327,6 @@
     : host_resolver(std::make_unique<MockCachingHostResolver>()),
       cert_verifier(std::make_unique<MockCertVerifier>()),
       transport_security_state(std::make_unique<TransportSecurityState>()),
-      cert_transparency_verifier(std::make_unique<DoNothingCTVerifier>()),
       ct_policy_enforcer(std::make_unique<DefaultCTPolicyEnforcer>()),
       proxy_resolution_service(std::move(proxy_resolution_service)),
       ssl_config_service(std::make_unique<SSLConfigServiceDefaults>()),
@@ -419,8 +417,6 @@
   context.cert_verifier = session_deps->cert_verifier.get();
   context.transport_security_state =
       session_deps->transport_security_state.get();
-  context.cert_transparency_verifier =
-      session_deps->cert_transparency_verifier.get();
   context.ct_policy_enforcer = session_deps->ct_policy_enforcer.get();
   context.proxy_resolution_service =
       session_deps->proxy_resolution_service.get();
@@ -448,8 +444,6 @@
   storage_.set_proxy_resolution_service(
       ConfiguredProxyResolutionService::CreateDirect());
   storage_.set_ct_policy_enforcer(std::make_unique<DefaultCTPolicyEnforcer>());
-  storage_.set_cert_transparency_verifier(
-      std::make_unique<DoNothingCTVerifier>());
   storage_.set_ssl_config_service(std::make_unique<SSLConfigServiceDefaults>());
   storage_.set_http_auth_handler_factory(
       HttpAuthHandlerFactory::CreateDefault());
@@ -466,7 +460,6 @@
   session_context.transport_security_state = transport_security_state();
   session_context.proxy_resolution_service = proxy_resolution_service();
   session_context.ct_policy_enforcer = ct_policy_enforcer();
-  session_context.cert_transparency_verifier = cert_transparency_verifier();
   session_context.ssl_config_service = ssl_config_service();
   session_context.http_auth_handler_factory = http_auth_handler_factory();
   session_context.http_server_properties = http_server_properties();
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index 49e4a18d..000d142 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -48,7 +48,6 @@
 
 namespace net {
 
-class CTVerifier;
 class CTPolicyEnforcer;
 class HashValue;
 class HostPortPair;
@@ -210,7 +209,6 @@
   std::unique_ptr<HostResolver> alternate_host_resolver;
   std::unique_ptr<CertVerifier> cert_verifier;
   std::unique_ptr<TransportSecurityState> transport_security_state;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer;
   std::unique_ptr<ProxyResolutionService> proxy_resolution_service;
   std::unique_ptr<HttpUserAgentSettings> http_user_agent_settings;
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index ee04f49..15dc836 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -42,7 +42,6 @@
       http_user_agent_settings_(nullptr),
       cookie_store_(nullptr),
       transport_security_state_(nullptr),
-      cert_transparency_verifier_(nullptr),
       ct_policy_enforcer_(nullptr),
       sct_auditing_delegate_(nullptr),
       http_transaction_factory_(nullptr),
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 9d6ff505..13ca8512 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -38,7 +38,6 @@
 class CertVerifier;
 class CookieStore;
 class CTPolicyEnforcer;
-class CTVerifier;
 class HostResolver;
 class HttpAuthHandlerFactory;
 class HttpTransactionFactory;
@@ -199,13 +198,6 @@
     transport_security_state_ = state;
   }
 
-  CTVerifier* cert_transparency_verifier() const {
-    return cert_transparency_verifier_;
-  }
-  void set_cert_transparency_verifier(CTVerifier* verifier) {
-    cert_transparency_verifier_ = verifier;
-  }
-
   CTPolicyEnforcer* ct_policy_enforcer() const { return ct_policy_enforcer_; }
   void set_ct_policy_enforcer(CTPolicyEnforcer* enforcer) {
     ct_policy_enforcer_ = enforcer;
@@ -340,7 +332,6 @@
   const HttpUserAgentSettings* http_user_agent_settings_;
   CookieStore* cookie_store_;
   TransportSecurityState* transport_security_state_;
-  CTVerifier* cert_transparency_verifier_;
   CTPolicyEnforcer* ct_policy_enforcer_;
   SCTAuditingDelegate* sct_auditing_delegate_;
   HttpTransactionFactory* http_transaction_factory_;
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 3117f28..d19aaf40 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -190,8 +190,6 @@
   session_context->cert_verifier = request_context->cert_verifier();
   session_context->transport_security_state =
       request_context->transport_security_state();
-  session_context->cert_transparency_verifier =
-      request_context->cert_transparency_verifier();
   session_context->ct_policy_enforcer = request_context->ct_policy_enforcer();
   session_context->sct_auditing_delegate =
       request_context->sct_auditing_delegate();
@@ -252,11 +250,6 @@
   http_network_session_params_.enable_quic = quic_enabled;
 }
 
-void URLRequestContextBuilder::set_ct_verifier(
-    std::unique_ptr<CTVerifier> ct_verifier) {
-  ct_verifier_ = std::move(ct_verifier);
-}
-
 void URLRequestContextBuilder::set_ct_policy_enforcer(
     std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer) {
   ct_policy_enforcer_ = std::move(ct_policy_enforcer);
@@ -468,12 +461,6 @@
         CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr));
   }
 
-  if (ct_verifier_) {
-    storage->set_cert_transparency_verifier(std::move(ct_verifier_));
-  } else {
-    storage->set_cert_transparency_verifier(
-        std::make_unique<MultiLogCTVerifier>());
-  }
   if (ct_policy_enforcer_) {
     storage->set_ct_policy_enforcer(std::move(ct_policy_enforcer_));
   } else {
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index e9d1010..713c74c0 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -53,7 +53,6 @@
 class CertVerifier;
 class CookieStore;
 class CTPolicyEnforcer;
-class CTVerifier;
 class HttpAuthHandlerFactory;
 class HttpTransactionFactory;
 class HttpUserAgentSettings;
@@ -275,7 +274,6 @@
     throttling_enabled_ = throttling_enabled;
   }
 
-  void set_ct_verifier(std::unique_ptr<CTVerifier> ct_verifier);
   void set_ct_policy_enforcer(
       std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer);
   void set_sct_auditing_delegate(
@@ -367,7 +365,6 @@
   std::unique_ptr<CookieStore> cookie_store_;
   std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
   std::unique_ptr<CertVerifier> cert_verifier_;
-  std::unique_ptr<CTVerifier> ct_verifier_;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_;
   std::unique_ptr<SCTAuditingDelegate> sct_auditing_delegate_;
   std::unique_ptr<QuicContext> quic_context_;
diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc
index f50b697..836202ca 100644
--- a/net/url_request/url_request_context_storage.cc
+++ b/net/url_request/url_request_context_storage.cc
@@ -12,7 +12,6 @@
 #include "net/base/proxy_delegate.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_verifier.h"
 #include "net/cert/sct_auditing_delegate.h"
 #include "net/cookies/cookie_store.h"
 #include "net/dns/host_resolver.h"
@@ -104,12 +103,6 @@
   transport_security_state_ = std::move(transport_security_state);
 }
 
-void URLRequestContextStorage::set_cert_transparency_verifier(
-    std::unique_ptr<CTVerifier> cert_transparency_verifier) {
-  context_->set_cert_transparency_verifier(cert_transparency_verifier.get());
-  cert_transparency_verifier_ = std::move(cert_transparency_verifier);
-}
-
 void URLRequestContextStorage::set_ct_policy_enforcer(
     std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer) {
   context_->set_ct_policy_enforcer(ct_policy_enforcer.get());
diff --git a/net/url_request/url_request_context_storage.h b/net/url_request/url_request_context_storage.h
index 713d9b2..d78511a 100644
--- a/net/url_request/url_request_context_storage.h
+++ b/net/url_request/url_request_context_storage.h
@@ -18,7 +18,6 @@
 class CertVerifier;
 class CookieStore;
 class CTPolicyEnforcer;
-class CTVerifier;
 class FtpAuthCache;
 class HostResolver;
 class HttpAuthHandlerFactory;
@@ -71,8 +70,6 @@
   void set_cookie_store(std::unique_ptr<CookieStore> cookie_store);
   void set_transport_security_state(
       std::unique_ptr<TransportSecurityState> transport_security_state);
-  void set_cert_transparency_verifier(
-      std::unique_ptr<CTVerifier> cert_transparency_verifier);
   void set_ct_policy_enforcer(
       std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer);
   void set_sct_auditing_delegate(
@@ -124,7 +121,6 @@
   std::unique_ptr<HttpUserAgentSettings> http_user_agent_settings_;
   std::unique_ptr<CookieStore> cookie_store_;
   std::unique_ptr<TransportSecurityState> transport_security_state_;
-  std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_;
   std::unique_ptr<SCTAuditingDelegate> sct_auditing_delegate_;
   std::unique_ptr<QuicContext> quic_context_;
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 0fef1f0..d0a70f24 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -97,10 +97,6 @@
     context_storage_.set_transport_security_state(
         std::make_unique<TransportSecurityState>());
   }
-  if (!cert_transparency_verifier()) {
-    context_storage_.set_cert_transparency_verifier(
-        std::make_unique<DoNothingCTVerifier>());
-  }
   if (!ct_policy_enforcer()) {
     context_storage_.set_ct_policy_enforcer(
         std::make_unique<DefaultCTPolicyEnforcer>());
@@ -145,7 +141,6 @@
     session_context.client_socket_factory = client_socket_factory();
     session_context.host_resolver = host_resolver();
     session_context.cert_verifier = cert_verifier();
-    session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
     session_context.transport_security_state = transport_security_state();
     session_context.proxy_resolution_service = proxy_resolution_service();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 77727d0..1560b089 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -5472,9 +5472,7 @@
   verify_result.is_issued_by_known_root = true;
   cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
 
-  // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to trigger an Expect
-  // CT violation.
-  DoNothingCTVerifier ct_verifier;
+  // Set up a MockCTPolicyEnforcer to trigger an Expect CT violation.
   MockCTPolicyEnforcer ct_policy_enforcer;
   ct_policy_enforcer.set_default_result(
       ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS);
@@ -5489,7 +5487,6 @@
   context.set_transport_security_state(&transport_security_state);
   context.set_network_delegate(&network_delegate);
   context.set_cert_verifier(&cert_verifier);
-  context.set_cert_transparency_verifier(&ct_verifier);
   context.set_ct_policy_enforcer(&ct_policy_enforcer);
   context.Init();
 
@@ -5533,9 +5530,7 @@
   verify_result.is_issued_by_known_root = true;
   cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
 
-  // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to simulate CT
-  // compliance.
-  DoNothingCTVerifier ct_verifier;
+  // Set up a MockCTPolicyEnforcer to simulate CT compliance.
   MockCTPolicyEnforcer ct_policy_enforcer;
   ct_policy_enforcer.set_default_result(
       ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS);
@@ -5549,7 +5544,6 @@
   context.set_transport_security_state(&transport_security_state);
   context.set_network_delegate(&network_delegate);
   context.set_cert_verifier(&cert_verifier);
-  context.set_cert_transparency_verifier(&ct_verifier);
   context.set_ct_policy_enforcer(&ct_policy_enforcer);
   context.Init();
 
@@ -5595,8 +5589,7 @@
   verify_result.is_issued_by_known_root = true;
   cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
 
-  // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to simulate CT
-  // compliance.
+  // Set up a MockCTPolicyEnforcer to simulate CT compliance.
   DoNothingCTVerifier ct_verifier;
   MockCTPolicyEnforcer ct_policy_enforcer;
   ct_policy_enforcer.set_default_result(
@@ -5611,7 +5604,6 @@
   context.set_transport_security_state(&transport_security_state);
   context.set_network_delegate(&network_delegate);
   context.set_cert_verifier(&cert_verifier);
-  context.set_cert_transparency_verifier(&ct_verifier);
   context.set_ct_policy_enforcer(&ct_policy_enforcer);
   context.Init();
 
@@ -9423,8 +9415,6 @@
   session_context.cert_verifier = default_context_.cert_verifier();
   session_context.transport_security_state =
       default_context_.transport_security_state();
-  session_context.cert_transparency_verifier =
-      default_context_.cert_transparency_verifier();
   session_context.ct_policy_enforcer = default_context_.ct_policy_enforcer();
   session_context.proxy_resolution_service =
       default_context_.proxy_resolution_service();
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc
index c024c6a..c6a322e5 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -22,7 +22,6 @@
 #include "net/cert/cert_verify_result.h"
 #include "net/cert/ct_policy_enforcer.h"
 #include "net/cert/ct_policy_status.h"
-#include "net/cert/do_nothing_ct_verifier.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 #include "net/cert/x509_certificate.h"
 #include "net/http/transport_security_state.h"
@@ -277,13 +276,11 @@
     socket_context_.transport_security_state =
         std::make_unique<net::TransportSecurityState>();
     socket_context_.cert_verifier = std::make_unique<FailingCertVerifier>();
-    socket_context_.ct_verifier = std::make_unique<net::DoNothingCTVerifier>();
     socket_context_.ct_policy_enforcer =
         std::make_unique<net::DefaultCTPolicyEnforcer>();
     socket_context_.client_context = std::make_unique<net::SSLClientContext>(
         nullptr /* default config */, socket_context_.cert_verifier.get(),
         socket_context_.transport_security_state.get(),
-        socket_context_.ct_verifier.get(),
         socket_context_.ct_policy_enforcer.get(),
         nullptr /* no session caching */, nullptr /* no sct auditing */);
 
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.h b/remoting/protocol/ssl_hmac_channel_authenticator.h
index 64be0c1..0a7700a 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.h
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.h
@@ -17,7 +17,6 @@
 namespace net {
 class CertVerifier;
 class CTPolicyEnforcer;
-class CTVerifier;
 class DrainableIOBuffer;
 class GrowableIOBuffer;
 class SSLClientContext;
@@ -84,7 +83,6 @@
     // Used in the CLIENT mode only.
     std::unique_ptr<net::TransportSecurityState> transport_security_state;
     std::unique_ptr<net::CertVerifier> cert_verifier;
-    std::unique_ptr<net::CTVerifier> ct_verifier;
     std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer;
     std::unique_ptr<net::SSLClientContext> client_context;
   };
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index db0ecdf..6644070 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -119,6 +119,7 @@
 #include "components/certificate_transparency/chrome_ct_policy_enforcer.h"
 #include "components/certificate_transparency/chrome_require_ct_delegate.h"
 #include "components/certificate_transparency/ct_known_logs.h"
+#include "net/cert/cert_and_ct_verifier.h"
 #include "net/cert/ct_log_verifier.h"
 #include "net/cert/multi_log_ct_verifier.h"
 #include "services/network/expect_ct_reporter.h"
@@ -1886,6 +1887,25 @@
       cert_verifier = CreateCertVerifier(creation_params, cert_net_fetcher_);
     }
 
+#if BUILDFLAG(IS_CT_SUPPORTED)
+    std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
+    if (!params_->ct_logs.empty()) {
+      for (const auto& log : params_->ct_logs) {
+        scoped_refptr<const net::CTLogVerifier> log_verifier =
+            net::CTLogVerifier::Create(log->public_key, log->name);
+        if (!log_verifier) {
+          // TODO: Signal bad configuration (such as bad key).
+          continue;
+        }
+        ct_logs.push_back(std::move(log_verifier));
+      }
+      auto ct_verifier = std::make_unique<net::MultiLogCTVerifier>();
+      ct_verifier->AddLogs(ct_logs);
+      cert_verifier = std::make_unique<net::CertAndCTVerifier>(
+          std::move(cert_verifier), std::move(ct_verifier));
+    }
+#endif  // BUILDFLAG(IS_CT_SUPPORTED)
+
     // Whether the cert verifier is remote or in-process, we should wrap it in
     // caching and coalescing layers to avoid extra verifications and IPCs.
     cert_verifier = std::make_unique<net::CachingCertVerifier>(
@@ -1907,6 +1927,38 @@
   builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
       *command_line, nullptr, std::move(cert_verifier)));
 
+#if BUILDFLAG(IS_CT_SUPPORTED)
+  if (params_->enforce_chrome_ct_policy) {
+    std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
+    std::vector<std::string> operated_by_google_logs;
+    if (!params_->ct_logs.empty()) {
+      for (const auto& log : params_->ct_logs) {
+        if (log->operated_by_google || log->disqualified_at) {
+          std::string log_id = crypto::SHA256HashString(log->public_key);
+          if (log->operated_by_google)
+            operated_by_google_logs.push_back(log_id);
+          if (log->disqualified_at) {
+            disqualified_logs.push_back(
+                std::make_pair(log_id, log->disqualified_at.value()));
+          }
+        }
+      }
+    }
+
+    std::sort(std::begin(operated_by_google_logs),
+              std::end(operated_by_google_logs));
+    std::sort(std::begin(disqualified_logs), std::end(disqualified_logs));
+
+    builder.set_ct_policy_enforcer(
+        std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>(
+            params_->ct_log_update_time, disqualified_logs,
+            operated_by_google_logs));
+  }
+
+  builder.set_sct_auditing_delegate(
+      std::make_unique<SCTAuditingDelegate>(weak_factory_.GetWeakPtr()));
+#endif  // BUILDFLAG(IS_CT_SUPPORTED)
+
   std::unique_ptr<NetworkServiceNetworkDelegate> network_delegate =
       std::make_unique<NetworkServiceNetworkDelegate>(
           params_->enable_referrers,
@@ -2136,50 +2188,6 @@
         return std::make_unique<ThrottlingNetworkTransactionFactory>(session);
       }));
 
-#if BUILDFLAG(IS_CT_SUPPORTED)
-  std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
-  std::vector<std::pair<std::string, base::TimeDelta>> disqualified_logs;
-  std::vector<std::string> operated_by_google_logs;
-
-  if (!params_->ct_logs.empty()) {
-    for (const auto& log : params_->ct_logs) {
-      if (log->operated_by_google || log->disqualified_at) {
-        std::string log_id = crypto::SHA256HashString(log->public_key);
-        if (log->operated_by_google)
-          operated_by_google_logs.push_back(log_id);
-        if (log->disqualified_at) {
-          disqualified_logs.push_back(
-              std::make_pair(log_id, log->disqualified_at.value()));
-        }
-      }
-      scoped_refptr<const net::CTLogVerifier> log_verifier =
-          net::CTLogVerifier::Create(log->public_key, log->name);
-      if (!log_verifier) {
-        // TODO: Signal bad configuration (such as bad key).
-        continue;
-      }
-      ct_logs.push_back(std::move(log_verifier));
-    }
-    auto ct_verifier = std::make_unique<net::MultiLogCTVerifier>();
-    ct_verifier->AddLogs(ct_logs);
-    builder.set_ct_verifier(std::move(ct_verifier));
-  }
-
-  if (params_->enforce_chrome_ct_policy) {
-    std::sort(std::begin(operated_by_google_logs),
-              std::end(operated_by_google_logs));
-    std::sort(std::begin(disqualified_logs), std::end(disqualified_logs));
-
-    builder.set_ct_policy_enforcer(
-        std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>(
-            params_->ct_log_update_time, disqualified_logs,
-            operated_by_google_logs));
-  }
-
-  builder.set_sct_auditing_delegate(
-      std::make_unique<SCTAuditingDelegate>(weak_factory_.GetWeakPtr()));
-#endif  // BUILDFLAG(IS_CT_SUPPORTED)
-
   builder.set_host_mapping_rules(
       command_line->GetSwitchValueASCII(switches::kHostResolverRules));
 
@@ -2389,13 +2397,6 @@
   if (result == net::OK) {
     net::X509Certificate* verified_cert =
         pending_cert_verify->result->verified_cert.get();
-    url_request_context_->cert_transparency_verifier()->Verify(
-        pending_cert_verify->url.host(), verified_cert,
-        pending_cert_verify->ocsp_result, pending_cert_verify->sct_list,
-        &pending_cert_verify->result->scts,
-        net::NetLogWithSource::Make(
-            network_service_ ? url_request_context_->net_log() : nullptr,
-            net::NetLogSourceType::CERT_VERIFIER_JOB));
 
     net::ct::SCTList verified_scts;
     for (const auto& sct_and_status : pending_cert_verify->result->scts) {
@@ -2433,8 +2434,7 @@
             pending_cert_verify->network_isolation_key);
 
     if (url_request_context_->sct_auditing_delegate() &&
-        url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled() &&
-        pending_cert_verify->result->is_issued_by_known_root) {
+        url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled()) {
       url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport(
           net::HostPortPair::FromURL(pending_cert_verify->url), verified_cert,
           pending_cert_verify->result->scts);
diff --git a/services/network/proxy_resolving_client_socket_factory.cc b/services/network/proxy_resolving_client_socket_factory.cc
index caa2d52a..99c3886e 100644
--- a/services/network/proxy_resolving_client_socket_factory.cc
+++ b/services/network/proxy_resolving_client_socket_factory.cc
@@ -26,8 +26,6 @@
   session_context.cert_verifier = request_context->cert_verifier();
   session_context.transport_security_state =
       request_context->transport_security_state();
-  session_context.cert_transparency_verifier =
-      request_context->cert_transparency_verifier();
   session_context.ct_policy_enforcer = request_context->ct_policy_enforcer();
   session_context.sct_auditing_delegate =
       request_context->sct_auditing_delegate();
diff --git a/services/network/sct_auditing_cache.cc b/services/network/sct_auditing_cache.cc
index b8de60e..e3e7378 100644
--- a/services/network/sct_auditing_cache.cc
+++ b/services/network/sct_auditing_cache.cc
@@ -19,6 +19,7 @@
 #include "net/base/request_priority.h"
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/cert/ct_serialization.h"
+#include "net/cert/sct_status_flags.h"
 #include "net/cert/signed_certificate_timestamp.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 #include "net/cert/x509_certificate.h"
@@ -42,27 +43,6 @@
 
 constexpr int kSendSCTReportTimeoutSeconds = 30;
 
-sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus
-MapSCTVerifyStatusToProtoStatus(net::ct::SCTVerifyStatus status) {
-  switch (status) {
-    case net::ct::SCTVerifyStatus::SCT_STATUS_NONE:
-      return sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
-          SCTWithSourceAndVerifyStatus_SctVerifyStatus_NONE;
-    case net::ct::SCTVerifyStatus::SCT_STATUS_LOG_UNKNOWN:
-      return sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
-          SCTWithSourceAndVerifyStatus_SctVerifyStatus_LOG_UNKNOWN;
-    case net::ct::SCTVerifyStatus::SCT_STATUS_OK:
-      return sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
-          SCTWithSourceAndVerifyStatus_SctVerifyStatus_OK;
-    case net::ct::SCTVerifyStatus::SCT_STATUS_INVALID_SIGNATURE:
-      return sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
-          SCTWithSourceAndVerifyStatus_SctVerifyStatus_INVALID_SIGNATURE;
-    case net::ct::SCTVerifyStatus::SCT_STATUS_INVALID_TIMESTAMP:
-      return sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
-          SCTWithSourceAndVerifyStatus_SctVerifyStatus_INVALID_TIMESTAMP;
-  }
-}
-
 sct_auditing::SCTWithSourceAndVerifyStatus::Source MapSCTOriginToSource(
     net::ct::SignedCertificateTimestamp::Origin origin) {
   switch (origin) {
@@ -173,16 +153,39 @@
   if (!enabled_ || !context->is_sct_auditing_enabled())
     return;
 
-  // Generate the cache key for this report. In order to have the cache
-  // deduplicate reports for the same SCTs, we compute the cache key as the
-  // hash of the SCTs.
+  auto report = std::make_unique<sct_auditing::TLSConnectionReport>();
+
+  // Encode the SCTs in the report and generate the cache key. The hash of the
+  // SCTs is used as the cache key to deduplicate reports with the same SCTs.
+  // Constructing the report in parallel with computing the hash avoids
+  // encoding the SCTs multiple times and avoids extra copies.
   SHA256_CTX ctx;
   SHA256_Init(&ctx);
   for (const auto& sct : signed_certificate_timestamps) {
-    std::string serialized_sct;
-    net::ct::EncodeSignedCertificateTimestamp(sct.sct, &serialized_sct);
-    SHA256_Update(&ctx, serialized_sct.data(), serialized_sct.size());
+    // Only audit valid SCTs. This ensures that they come from a known log, have
+    // a valid signature, and thus are expected to be public certificates. If
+    // there are no valid SCTs, there's no need to report anything.
+    if (sct.status != net::ct::SCT_STATUS_OK)
+      continue;
+
+    auto* sct_source_and_status = report->add_included_scts();
+    // TODO(crbug.com/1082860): Update the proto to remove the status entirely
+    // since only valid SCTs are reported now.
+    sct_source_and_status->set_status(
+        sct_auditing::SCTWithSourceAndVerifyStatus::SctVerifyStatus::
+            SCTWithSourceAndVerifyStatus_SctVerifyStatus_OK);
+
+    sct_source_and_status->set_source(MapSCTOriginToSource(sct.sct->origin));
+    net::ct::EncodeSignedCertificateTimestamp(
+        sct.sct, sct_source_and_status->mutable_sct());
+
+    SHA256_Update(&ctx, sct_source_and_status->sct().data(),
+                  sct_source_and_status->sct().size());
   }
+  // Don't handle reports if there were no valid SCTs.
+  if (report->included_scts().empty())
+    return;
+
   net::SHA256HashValue cache_key;
   SHA256_Final(reinterpret_cast<uint8_t*>(&cache_key), &ctx);
 
@@ -207,10 +210,7 @@
   }
   RecordSCTAuditingReportSampledMetrics(true);
 
-  // Insert SCTs into cache.
-  auto report = std::make_unique<sct_auditing::TLSConnectionReport>();
   auto* connection_context = report->mutable_context();
-
   base::TimeDelta time_since_unix_epoch =
       base::Time::Now() - base::Time::UnixEpoch();
   connection_context->set_time_seen(time_since_unix_epoch.InSeconds());
@@ -228,16 +228,6 @@
   *connection_context->mutable_certificate_chain() = {certificate_chain.begin(),
                                                       certificate_chain.end()};
 
-  for (const auto& sct : signed_certificate_timestamps) {
-    auto* sct_source_and_status = report->add_included_scts();
-    sct_source_and_status->set_status(
-        MapSCTVerifyStatusToProtoStatus(sct.status));
-    sct_source_and_status->set_source(MapSCTOriginToSource(sct.sct->origin));
-    std::string serialized_sct;
-    net::ct::EncodeSignedCertificateTimestamp(sct.sct, &serialized_sct);
-    sct_source_and_status->set_sct(serialized_sct);
-  }
-
   // Log the size of the report. This only tracks reports that are not dropped
   // due to sampling (as those reports will just be empty).
   RecordSCTAuditingReportSizeMetrics(report->ByteSizeLong());
diff --git a/services/network/sct_auditing_cache_unittest.cc b/services/network/sct_auditing_cache_unittest.cc
index 60d8527..bbcf943 100644
--- a/services/network/sct_auditing_cache_unittest.cc
+++ b/services/network/sct_auditing_cache_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "net/base/host_port_pair.h"
+#include "net/cert/ct_serialization.h"
 #include "net/cert/sct_status_flags.h"
 #include "net/cert/signed_certificate_timestamp.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
@@ -149,7 +150,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions1", "signature1", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -165,7 +166,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions1", "signature1", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -185,7 +186,7 @@
     net::SignedCertificateTimestampAndStatusList sct_list;
     MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                          "extensions1", "signature1", base::Time::Now(),
-                         net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                         net::ct::SCT_STATUS_OK, &sct_list);
     cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
                              chain_.get(), sct_list);
     ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
@@ -195,7 +196,7 @@
     net::SignedCertificateTimestampAndStatusList sct_list;
     MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                          "extensions1", "signature2", base::Time::Now(),
-                         net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                         net::ct::SCT_STATUS_OK, &sct_list);
     cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
                              chain_.get(), sct_list);
     ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
@@ -207,7 +208,7 @@
     net::SignedCertificateTimestampAndStatusList sct_list;
     MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                          "extensions1", "signature3", base::Time::Now(),
-                         net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                         net::ct::SCT_STATUS_OK, &sct_list);
     cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
                              chain_.get(), sct_list);
     ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
@@ -229,7 +230,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions1", "signature1", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
                            chain_.get(), sct_list);
 
@@ -256,14 +257,14 @@
   net::SignedCertificateTimestampAndStatusList sct_list1;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions1", "signature1", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list1);
+                       net::ct::SCT_STATUS_OK, &sct_list1);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
                            chain_.get(), sct_list1);
 
   net::SignedCertificateTimestampAndStatusList sct_list2;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions2", "signature2", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list2);
+                       net::ct::SCT_STATUS_OK, &sct_list2);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
                            chain_.get(), sct_list2);
 
@@ -280,7 +281,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list3;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions3", "signature3", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list3);
+                       net::ct::SCT_STATUS_OK, &sct_list3);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
                            chain_.get(), sct_list3);
 
@@ -300,7 +301,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -318,7 +319,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -342,7 +343,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -375,7 +376,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -412,14 +413,14 @@
     net::SignedCertificateTimestampAndStatusList sct_list1;
     MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                          "extensions1", "signature1", base::Time::Now(),
-                         net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list1);
+                         net::ct::SCT_STATUS_OK, &sct_list1);
     cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
                              chain_.get(), sct_list1);
 
     net::SignedCertificateTimestampAndStatusList sct_list2;
     MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                          "extensions2", "signature2", base::Time::Now(),
-                         net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list2);
+                         net::ct::SCT_STATUS_OK, &sct_list2);
     cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
                              chain_.get(), sct_list2);
 
@@ -444,7 +445,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -478,7 +479,7 @@
   net::SignedCertificateTimestampAndStatusList sct_list;
   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
                        "extensions", "signature", base::Time::Now(),
-                       net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+                       net::ct::SCT_STATUS_OK, &sct_list);
   cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
                            sct_list);
 
@@ -489,4 +490,56 @@
                                false, 1);
 }
 
+// If a report doesn't have any valid SCTs, it should not get added to the cache
+// at all.
+TEST_F(SCTAuditingCacheTest, ReportNotGeneratedIfNoValidSCTs) {
+  SCTAuditingCache cache(10);
+  InitSCTAuditing(&cache);
+
+  const net::HostPortPair host_port_pair("example.com", 443);
+  net::SignedCertificateTimestampAndStatusList sct_list;
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "extensions", "signature", base::Time::Now(),
+                       net::ct::SCT_STATUS_INVALID_SIGNATURE, &sct_list);
+  cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+                           sct_list);
+
+  EXPECT_EQ(0u, cache.GetCacheForTesting()->size());
+}
+
+// Connections that have a mix of valid and invalid SCTs should only include the
+// valid SCTs in the report.
+TEST_F(SCTAuditingCacheTest, ReportsOnlyIncludesValidSCTs) {
+  SCTAuditingCache cache(10);
+  InitSCTAuditing(&cache);
+
+  // Add a report with different types and validities of SCTs.
+  const net::HostPortPair host_port_pair("example.com", 443);
+  net::SignedCertificateTimestampAndStatusList sct_list;
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "extensions1", "valid_signature", base::Time::Now(),
+                       net::ct::SCT_STATUS_OK, &sct_list);
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "extensions2", "invalid_signature", base::Time::Now(),
+                       net::ct::SCT_STATUS_INVALID_SIGNATURE, &sct_list);
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
+      "extensions3", "invalid_log", base::Time::Now(),
+      net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+  cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+                           sct_list);
+
+  // No invalid SCTs should be in any reports in the cache.
+  for (const auto& entry : *cache.GetCacheForTesting()) {
+    for (auto& sct_and_status : entry.second->included_scts()) {
+      // Decode the SCT and check that only the valid SCT was included.
+      base::StringPiece encoded_sct(sct_and_status.sct());
+      scoped_refptr<net::ct::SignedCertificateTimestamp> decoded_sct;
+      ASSERT_TRUE(net::ct::DecodeSignedCertificateTimestamp(&encoded_sct,
+                                                            &decoded_sct));
+      EXPECT_EQ("valid_signature", decoded_sct->signature.signature_data);
+    }
+  }
+}
+
 }  // namespace network
diff --git a/services/network/tls_socket_factory.cc b/services/network/tls_socket_factory.cc
index dd9f199..83b5126 100644
--- a/services/network/tls_socket_factory.cc
+++ b/services/network/tls_socket_factory.cc
@@ -49,7 +49,6 @@
     : ssl_client_context_(url_request_context->ssl_config_service(),
                           url_request_context->cert_verifier(),
                           url_request_context->transport_security_state(),
-                          url_request_context->cert_transparency_verifier(),
                           url_request_context->ct_policy_enforcer(),
                           nullptr /* Disables SSL session caching */,
                           url_request_context->sct_auditing_delegate()),
@@ -123,15 +122,12 @@
         no_verification_cert_verifier_ = std::make_unique<FakeCertVerifier>();
         no_verification_transport_security_state_ =
             std::make_unique<net::TransportSecurityState>();
-        no_verification_cert_transparency_verifier_ =
-            std::make_unique<net::MultiLogCTVerifier>();
         no_verification_ct_policy_enforcer_ =
             std::make_unique<net::DefaultCTPolicyEnforcer>();
         no_verification_ssl_client_context_ =
             std::make_unique<net::SSLClientContext>(
                 ssl_config_service_, no_verification_cert_verifier_.get(),
                 no_verification_transport_security_state_.get(),
-                no_verification_cert_transparency_verifier_.get(),
                 no_verification_ct_policy_enforcer_.get(),
                 nullptr /* no session cache */,
                 nullptr /* disable sct auditing */);
diff --git a/services/network/tls_socket_factory.h b/services/network/tls_socket_factory.h
index ec96c719..5a15ca7 100644
--- a/services/network/tls_socket_factory.h
+++ b/services/network/tls_socket_factory.h
@@ -82,7 +82,6 @@
   std::unique_ptr<net::CertVerifier> no_verification_cert_verifier_;
   std::unique_ptr<net::TransportSecurityState>
       no_verification_transport_security_state_;
-  std::unique_ptr<net::CTVerifier> no_verification_cert_transparency_verifier_;
   std::unique_ptr<net::CTPolicyEnforcer> no_verification_ct_policy_enforcer_;
 
   net::SSLClientContext ssl_client_context_;
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 1f835c7..4b4241e 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -41184,9 +41184,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41229,9 +41226,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41274,9 +41268,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41319,9 +41310,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41364,9 +41352,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41409,9 +41394,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41454,9 +41436,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41499,9 +41478,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41544,9 +41520,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41589,9 +41562,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41634,9 +41604,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41679,9 +41646,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41724,9 +41688,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41769,9 +41730,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41814,9 +41772,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41859,9 +41814,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41904,9 +41856,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41949,9 +41898,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42014,9 +41960,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42058,9 +42001,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42102,9 +42042,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42146,9 +42083,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42190,9 +42124,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42234,9 +42165,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42278,9 +42206,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42322,9 +42247,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42366,9 +42288,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42410,9 +42329,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42454,9 +42370,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42498,9 +42411,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42542,9 +42452,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42586,9 +42493,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42630,9 +42534,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42674,9 +42575,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42718,9 +42616,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42762,9 +42657,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6S 12.3.1",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index b71a745..ccbc638 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -15385,9 +15385,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15430,9 +15427,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15475,9 +15469,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15520,9 +15511,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15565,9 +15553,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15610,9 +15595,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15655,9 +15637,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15700,9 +15679,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15745,9 +15721,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15790,9 +15763,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15835,9 +15805,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15880,9 +15847,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15925,9 +15889,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15970,9 +15931,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16015,9 +15973,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16060,9 +16015,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16105,9 +16057,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16150,9 +16099,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16195,9 +16141,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16240,9 +16183,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16285,9 +16225,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16330,9 +16267,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16375,9 +16309,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16420,9 +16351,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16465,9 +16393,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16510,9 +16435,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16555,9 +16477,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16600,9 +16519,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16645,9 +16561,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16690,9 +16603,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16735,9 +16645,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16780,9 +16687,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16825,9 +16729,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16870,9 +16771,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16915,9 +16813,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16960,9 +16855,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17005,9 +16897,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17050,9 +16939,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17095,9 +16981,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17140,9 +17023,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17185,9 +17065,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17230,9 +17107,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17275,9 +17149,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17320,9 +17191,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17365,9 +17233,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17410,9 +17275,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17462,9 +17324,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17510,9 +17369,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17558,9 +17414,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17606,9 +17459,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17654,9 +17504,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17702,9 +17549,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17750,9 +17594,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17798,9 +17639,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17846,9 +17684,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17894,9 +17729,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17942,9 +17774,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17990,9 +17819,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18038,9 +17864,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18086,9 +17909,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18134,9 +17954,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18182,9 +17999,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18230,9 +18044,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18278,9 +18089,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18326,9 +18134,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18374,9 +18179,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18422,9 +18224,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18470,9 +18269,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18518,9 +18314,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18566,9 +18359,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18614,9 +18404,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18662,9 +18449,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18710,9 +18494,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18758,9 +18539,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18806,9 +18584,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18854,9 +18629,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18902,9 +18674,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18950,9 +18719,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18998,9 +18764,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19046,9 +18809,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19095,9 +18855,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19144,9 +18901,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19193,9 +18947,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19242,9 +18993,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19291,9 +19039,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19340,9 +19085,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19389,9 +19131,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19439,9 +19178,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19489,9 +19225,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19539,9 +19272,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19589,9 +19319,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19639,9 +19366,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19689,9 +19413,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19739,9 +19460,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19789,9 +19507,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19839,9 +19554,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19889,9 +19601,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19939,9 +19648,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19989,9 +19695,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20038,9 +19741,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20087,9 +19787,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20136,9 +19833,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20185,9 +19879,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20234,9 +19925,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20283,9 +19971,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20332,9 +20017,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20381,9 +20063,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20430,9 +20109,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20479,9 +20155,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20528,9 +20201,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20577,9 +20247,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20627,9 +20294,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20677,9 +20341,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20727,9 +20388,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20777,9 +20435,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20827,9 +20482,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20876,9 +20528,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20924,9 +20573,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20972,9 +20618,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21020,9 +20663,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21068,9 +20708,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21116,9 +20753,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21164,9 +20798,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21212,9 +20843,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21261,9 +20889,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21310,9 +20935,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21359,9 +20981,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21408,9 +21027,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21457,9 +21073,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21506,9 +21119,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21554,9 +21164,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21602,9 +21209,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21650,9 +21254,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21698,9 +21299,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21746,9 +21344,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21794,9 +21389,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21843,9 +21435,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21892,9 +21481,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21941,9 +21527,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21990,9 +21573,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22039,9 +21619,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22088,9 +21665,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22136,9 +21710,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22184,9 +21755,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22232,9 +21800,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22280,9 +21845,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22328,9 +21890,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22376,9 +21935,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22424,9 +21980,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22472,9 +22025,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22520,9 +22070,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22568,9 +22115,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22617,9 +22161,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22666,9 +22207,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22715,9 +22253,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22764,9 +22299,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22813,9 +22345,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22862,9 +22391,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22910,9 +22436,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22958,9 +22481,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23006,9 +22526,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23054,9 +22571,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23102,9 +22616,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23150,9 +22661,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23198,9 +22706,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23246,9 +22751,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23294,9 +22796,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23342,9 +22841,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23390,9 +22886,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23438,9 +22931,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23486,9 +22976,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23534,9 +23021,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23582,9 +23066,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23630,9 +23111,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23678,9 +23156,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23726,9 +23201,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23774,9 +23246,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23822,9 +23291,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23870,9 +23336,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23918,9 +23381,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23966,9 +23426,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24014,9 +23471,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24062,9 +23516,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24110,9 +23561,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24158,9 +23606,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24206,9 +23651,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24254,9 +23696,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24302,9 +23741,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24350,9 +23786,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24398,9 +23831,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24446,9 +23876,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24494,9 +23921,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24542,9 +23966,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24590,9 +24011,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24638,9 +24056,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24686,9 +24101,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24734,9 +24146,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24782,9 +24191,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24830,9 +24236,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24878,9 +24281,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24926,9 +24326,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24974,9 +24371,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25022,9 +24416,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25070,9 +24461,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25118,9 +24506,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25166,9 +24551,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25216,9 +24598,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25262,9 +24641,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25308,9 +24684,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25354,9 +24727,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25400,9 +24770,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25446,9 +24813,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25492,9 +24856,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25538,9 +24899,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25584,9 +24942,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25630,9 +24985,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25676,9 +25028,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25722,9 +25071,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25768,9 +25114,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25814,9 +25157,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25860,9 +25200,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25906,9 +25243,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25952,9 +25286,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25998,9 +25329,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26044,9 +25372,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26090,9 +25415,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26136,9 +25458,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26182,9 +25501,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26228,9 +25544,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26274,9 +25587,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26320,9 +25630,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26366,9 +25673,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26412,9 +25716,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26458,9 +25759,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26504,9 +25802,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26550,9 +25845,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26596,9 +25888,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26642,9 +25931,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26688,9 +25974,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26734,9 +26017,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26781,9 +26061,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26829,9 +26106,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26877,9 +26151,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26924,9 +26195,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26971,9 +26239,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27019,9 +26284,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27066,9 +26328,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27112,9 +26371,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27158,9 +26414,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27204,9 +26457,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27250,9 +26500,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27296,9 +26543,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27342,9 +26586,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27388,9 +26629,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27434,9 +26672,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27480,9 +26715,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27526,9 +26758,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27572,9 +26801,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27618,9 +26844,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27664,9 +26887,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27710,9 +26930,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27756,9 +26973,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27802,9 +27016,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27848,9 +27059,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27894,9 +27102,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27940,9 +27145,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27986,9 +27188,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28032,9 +27231,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28078,9 +27274,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28124,9 +27317,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28171,9 +27361,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28218,9 +27405,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28264,9 +27448,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28310,9 +27491,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28356,9 +27534,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28402,9 +27577,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28448,9 +27620,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28494,9 +27663,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28540,9 +27706,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28586,9 +27749,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28632,9 +27792,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28678,9 +27835,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28724,9 +27878,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28770,9 +27921,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28816,9 +27964,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28862,9 +28007,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28908,9 +28050,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28954,9 +28093,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29000,9 +28136,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29046,9 +28179,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29092,9 +28222,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29138,9 +28265,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29184,9 +28308,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29230,9 +28351,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29276,9 +28394,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29322,9 +28437,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29368,9 +28480,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29414,9 +28523,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29460,9 +28566,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29506,9 +28609,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29552,9 +28652,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29598,9 +28695,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29644,9 +28738,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29690,9 +28781,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29736,9 +28824,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29782,9 +28867,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29828,9 +28910,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29874,9 +28953,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29920,9 +28996,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29966,9 +29039,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30012,9 +29082,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30058,9 +29125,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30104,9 +29168,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30150,9 +29211,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30196,9 +29254,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30242,9 +29297,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30288,9 +29340,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30334,9 +29383,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30380,9 +29426,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30426,9 +29469,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30475,9 +29515,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "cronet_test_iPhone X 12.4",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30520,9 +29557,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "cronet_test_iPhone X 13.4",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30571,9 +29605,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30618,9 +29649,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30665,9 +29693,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30712,9 +29737,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30759,9 +29781,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30806,9 +29825,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30853,9 +29869,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30901,9 +29914,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30949,9 +29959,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30997,9 +30004,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31045,9 +30049,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31093,9 +30094,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31141,9 +30139,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31189,9 +30184,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31237,9 +30229,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31285,9 +30274,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31333,9 +30319,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31380,9 +30363,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31427,9 +30407,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31474,9 +30451,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31521,9 +30495,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31568,9 +30539,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31615,9 +30583,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31662,9 +30627,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31709,9 +30671,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31756,9 +30715,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31803,9 +30759,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31851,9 +30804,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31899,9 +30849,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31947,9 +30894,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31995,9 +30939,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32042,9 +30983,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32089,9 +31027,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32136,9 +31071,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32183,9 +31115,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32230,9 +31159,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32277,9 +31203,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32324,9 +31247,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32371,9 +31291,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32418,9 +31335,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32465,9 +31379,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32512,9 +31423,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32559,9 +31467,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32606,9 +31511,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32653,9 +31555,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32700,9 +31599,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32749,9 +31645,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32794,9 +31687,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32839,9 +31729,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32884,9 +31771,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32929,9 +31813,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32974,9 +31855,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33019,9 +31897,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33064,9 +31939,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33110,9 +31982,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33156,9 +32025,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33203,9 +32069,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33250,9 +32113,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33296,9 +32156,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33342,9 +32199,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33388,9 +32242,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33434,9 +32285,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33479,9 +32327,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33524,9 +32369,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33569,9 +32411,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33615,9 +32454,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33660,9 +32496,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33705,9 +32538,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33751,9 +32581,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33796,9 +32623,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33841,9 +32665,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33886,9 +32707,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33931,9 +32749,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33976,9 +32791,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34021,9 +32833,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34066,9 +32875,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34111,9 +32917,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34156,9 +32959,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34207,9 +33007,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34254,9 +33051,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34301,9 +33095,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34348,9 +33139,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34395,9 +33183,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34442,9 +33227,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34489,9 +33271,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34536,9 +33315,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34583,9 +33359,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34630,9 +33403,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34677,9 +33447,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34724,9 +33491,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34771,9 +33535,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34818,9 +33579,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34865,9 +33623,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34912,9 +33667,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34960,9 +33712,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35008,9 +33757,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35056,9 +33802,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35105,9 +33848,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35154,9 +33894,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35203,9 +33940,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35252,9 +33986,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35300,9 +34031,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35348,9 +34076,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35396,9 +34121,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35444,9 +34166,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35493,9 +34212,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35541,9 +34257,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35588,9 +34301,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35636,9 +34346,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35684,9 +34391,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35731,9 +34435,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35778,9 +34479,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35825,9 +34523,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35872,9 +34567,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35919,9 +34611,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35966,9 +34655,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36014,9 +34700,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36062,9 +34745,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36109,9 +34789,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36156,9 +34833,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36203,9 +34877,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36250,9 +34921,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36298,9 +34966,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36346,9 +35011,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36393,9 +35055,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36440,9 +35099,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36487,9 +35143,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36534,9 +35187,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36581,9 +35231,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36628,9 +35275,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36675,9 +35319,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36722,9 +35363,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36769,9 +35407,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36816,9 +35451,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36863,9 +35495,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36910,9 +35539,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36957,9 +35583,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37004,9 +35627,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37051,9 +35671,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37098,9 +35715,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37145,9 +35759,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37192,9 +35803,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 13.5",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37259,9 +35867,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37304,9 +35909,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37349,9 +35951,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37394,9 +35993,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37439,9 +36035,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37484,9 +36077,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37529,9 +36119,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37574,9 +36161,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37619,9 +36203,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37664,9 +36245,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37709,9 +36287,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37754,9 +36329,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37799,9 +36371,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37844,9 +36413,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37890,9 +36456,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37936,9 +36499,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air (3rd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -37982,9 +36542,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38028,9 +36585,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38074,9 +36628,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38121,9 +36672,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38168,9 +36716,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38215,9 +36760,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38262,9 +36804,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38309,9 +36848,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air (3rd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38356,9 +36892,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38403,9 +36936,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38450,9 +36980,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38496,9 +37023,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38542,9 +37066,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38588,9 +37109,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38634,9 +37152,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38680,9 +37195,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air (3rd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38726,9 +37238,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38772,9 +37281,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38818,9 +37324,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38865,9 +37368,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38912,9 +37412,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -38959,9 +37456,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39005,9 +37499,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39050,9 +37541,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39095,9 +37583,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39141,9 +37626,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39187,9 +37669,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air (3rd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39233,9 +37712,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39279,9 +37755,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39324,9 +37797,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39369,9 +37839,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39414,9 +37881,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39460,9 +37924,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39506,9 +37967,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air (3rd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39552,9 +38010,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39598,9 +38053,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39643,9 +38095,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39688,9 +38137,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39733,9 +38179,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39778,9 +38221,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39824,9 +38264,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad (6th generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39870,9 +38307,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39916,9 +38350,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -39962,9 +38393,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40007,9 +38435,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40052,9 +38477,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40097,9 +38519,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40142,9 +38561,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40187,9 +38603,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40232,9 +38645,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40277,9 +38687,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40322,9 +38729,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40367,9 +38771,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40412,9 +38813,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40457,9 +38855,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40502,9 +38897,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40547,9 +38939,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40592,9 +38981,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40637,9 +39023,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40682,9 +39065,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40727,9 +39107,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40772,9 +39149,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40817,9 +39191,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40869,9 +39240,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40914,9 +39282,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -40959,9 +39324,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41004,9 +39366,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41049,9 +39408,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41094,9 +39450,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41139,9 +39492,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41184,9 +39534,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41229,9 +39576,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41274,9 +39618,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41319,9 +39660,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41365,9 +39703,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41411,9 +39746,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41457,9 +39789,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41503,9 +39832,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41550,9 +39876,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41597,9 +39920,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41644,9 +39964,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41691,9 +40008,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41738,9 +40052,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41785,9 +40096,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41831,9 +40139,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41877,9 +40182,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41923,9 +40225,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41969,9 +40268,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42015,9 +40311,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42061,9 +40354,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42108,9 +40398,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42155,9 +40442,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42201,9 +40485,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42246,9 +40527,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42292,9 +40570,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42338,9 +40613,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42384,9 +40656,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42429,9 +40698,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42474,9 +40740,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42519,9 +40782,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42565,9 +40825,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42611,9 +40868,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42657,9 +40911,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42702,9 +40953,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42747,9 +40995,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42792,9 +41037,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42838,9 +41080,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42884,9 +41123,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42930,9 +41166,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42975,9 +41208,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43020,9 +41250,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43065,9 +41292,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43110,9 +41334,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43155,9 +41376,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43200,9 +41418,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43245,9 +41460,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43290,9 +41502,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43335,9 +41544,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43380,9 +41586,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43425,9 +41628,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43470,9 +41670,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43515,9 +41712,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -43560,9 +41754,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.2",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 9068691..6689b563 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -10790,9 +10790,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -10835,9 +10832,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -10880,9 +10874,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -10925,9 +10916,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -10970,9 +10958,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11015,9 +11000,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11060,9 +11042,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11105,9 +11084,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11150,9 +11126,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11195,9 +11168,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11240,9 +11210,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11285,9 +11252,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11330,9 +11294,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11375,9 +11336,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11420,9 +11378,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11465,9 +11420,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11510,9 +11462,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11555,9 +11504,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11600,9 +11546,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11645,9 +11588,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11690,9 +11630,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11735,9 +11672,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11780,9 +11714,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11825,9 +11756,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11870,9 +11798,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11915,9 +11840,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -11960,9 +11882,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12005,9 +11924,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12050,9 +11966,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12095,9 +12008,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12140,9 +12050,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12185,9 +12092,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12230,9 +12134,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12275,9 +12176,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12321,9 +12219,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12368,9 +12263,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12415,9 +12307,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12461,9 +12350,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12507,9 +12393,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12554,9 +12437,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12600,9 +12480,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12645,9 +12522,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12690,9 +12564,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12735,9 +12606,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12780,9 +12648,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12825,9 +12690,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12870,9 +12732,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12915,9 +12774,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -12960,9 +12816,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13005,9 +12858,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13050,9 +12900,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13095,9 +12942,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13140,9 +12984,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13185,9 +13026,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13230,9 +13068,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13275,9 +13110,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13320,9 +13152,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13365,9 +13194,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13410,9 +13236,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13455,9 +13278,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13500,9 +13320,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13545,9 +13362,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13590,9 +13404,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13635,9 +13446,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13681,9 +13489,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13727,9 +13532,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13772,9 +13574,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13817,9 +13616,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13862,9 +13658,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13907,9 +13700,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13952,9 +13742,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -13997,9 +13784,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14042,9 +13826,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14087,9 +13868,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14132,9 +13910,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14177,9 +13952,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14222,9 +13994,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14267,9 +14036,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14312,9 +14078,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14357,9 +14120,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14402,9 +14162,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14447,9 +14204,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14492,9 +14246,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14537,9 +14288,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14582,9 +14330,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14627,9 +14372,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14672,9 +14414,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14717,9 +14456,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14762,9 +14498,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14807,9 +14540,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14852,9 +14582,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14897,9 +14624,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14942,9 +14666,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14987,9 +14708,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15032,9 +14750,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15077,9 +14792,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15122,9 +14834,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15167,9 +14876,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15212,9 +14918,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15257,9 +14960,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15302,9 +15002,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15347,9 +15044,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15392,9 +15086,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15437,9 +15128,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15482,9 +15170,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15527,9 +15212,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15572,9 +15254,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15617,9 +15296,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15662,9 +15338,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15707,9 +15380,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15752,9 +15422,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15797,9 +15464,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15842,9 +15506,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15887,9 +15548,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15940,9 +15598,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15986,9 +15641,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16032,9 +15684,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16078,9 +15727,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16124,9 +15770,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16170,9 +15813,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16216,9 +15856,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16263,9 +15900,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16310,9 +15944,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16357,9 +15988,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16404,9 +16032,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16451,9 +16076,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16498,9 +16120,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16545,9 +16164,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16592,9 +16208,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16639,9 +16252,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16686,9 +16296,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16732,9 +16339,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16778,9 +16382,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16824,9 +16425,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16870,9 +16468,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16916,9 +16511,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16962,9 +16554,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17008,9 +16597,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17054,9 +16640,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17100,9 +16683,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17146,9 +16726,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17193,9 +16770,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17240,9 +16814,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17287,9 +16858,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17334,9 +16902,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17380,9 +16945,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17426,9 +16988,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17472,9 +17031,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17518,9 +17074,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17564,9 +17117,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17610,9 +17160,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17656,9 +17203,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17702,9 +17246,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17748,9 +17289,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17794,9 +17332,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17840,9 +17375,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17886,9 +17418,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17932,9 +17461,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17978,9 +17504,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 13.6",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18024,9 +17547,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.0",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18076,9 +17596,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18121,9 +17638,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18166,9 +17680,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18211,9 +17722,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18256,9 +17764,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18302,9 +17807,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18348,9 +17850,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18394,9 +17893,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18441,9 +17937,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18488,9 +17981,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18535,9 +18025,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18582,9 +18069,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18628,9 +18112,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18674,9 +18155,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18720,9 +18198,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18766,9 +18241,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18813,9 +18285,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18860,9 +18329,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18906,9 +18372,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18951,9 +18414,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18996,9 +18456,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19041,9 +18498,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19087,9 +18541,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19133,9 +18584,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19178,9 +18626,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19224,9 +18669,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19270,9 +18712,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19315,9 +18754,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19360,9 +18796,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19405,9 +18838,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19450,9 +18880,6 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 12.4",
-        "resultdb": {
-          "enable": false
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index d9f118ad..19567905 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -220,6 +220,52 @@
       }
     ]
   },
+  "fuchsia-perf-fyi": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "-v",
+          "--browser=release",
+          "--upload-results",
+          "--test-shard-map-filename=fuchsia-perf-fyi_map.json",
+          "--output-format=histograms",
+          "--experimental-tbmv3-metrics"
+        ],
+        "isolate_name": "performance_test_suite",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "performance_test_suite",
+        "override_compile_targets": [
+          "performance_test_suite"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "Astro",
+              "os": "Fuchsia",
+              "pool": "chrome.tests"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 21600,
+          "ignore_task_failure": false,
+          "io_timeout": 21600,
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      }
+    ]
+  },
   "linux-perf-fyi": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/chromium.updater.json b/testing/buildbot/chromium.updater.json
index cfe90c462..c3b94db 100644
--- a/testing/buildbot/chromium.updater.json
+++ b/testing/buildbot/chromium.updater.json
@@ -425,6 +425,96 @@
       }
     ]
   },
+  "win7(32)-updater-tester-dbg": {
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-32",
+              "integrity": "high",
+              "os": "Windows-7-SP1"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "updater_tests",
+        "test_id_prefix": "ninja://chrome/updater:updater_tests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "updater_integration_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "updater_integration_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-32",
+              "integrity": "high",
+              "os": "Windows-7-SP1"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/updater:updater_integration_tests/"
+      }
+    ]
+  },
+  "win7(32)-updater-tester-rel": {
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-32",
+              "integrity": "high",
+              "os": "Windows-7-SP1"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "updater_tests",
+        "test_id_prefix": "ninja://chrome/updater:updater_tests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "updater_integration_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "updater_integration_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-32",
+              "integrity": "high",
+              "os": "Windows-7-SP1"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/updater:updater_integration_tests/"
+      }
+    ]
+  },
   "win7-updater-tester-dbg": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index cc5ed87..a6b0009c 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3618,44 +3618,44 @@
     },
 
     'ios_clang_tests': {
-      'absl_hardening_tests': {'resultdb':{'enable':False}},
-      'base_unittests': {'resultdb':{'enable':False}},
-      'boringssl_crypto_tests': {'resultdb':{'enable':False}},
-      'boringssl_ssl_tests': {'resultdb':{'enable':False}},
-      'components_unittests': {'resultdb':{'enable':False}},
-      'crypto_unittests': {'resultdb':{'enable':False}},
-      'gfx_unittests': {'resultdb':{'enable':False}},
-      'google_apis_unittests': {'resultdb':{'enable':False}},
-      'ios_chrome_unittests': {'resultdb':{'enable':False}},
-      'ios_net_unittests': {'resultdb':{'enable':False}},
-      'ios_web_inttests': {'resultdb':{'enable':False}},
-      'ios_web_unittests': {'resultdb':{'enable':False}},
-      'ios_web_view_inttests': {'resultdb':{'enable':False}},
-      'net_unittests': {'resultdb':{'enable':False}},
-      'skia_unittests': {'resultdb':{'enable':False}},
-      'sql_unittests': {'resultdb':{'enable':False}},
-      'ui_base_unittests': {'resultdb':{'enable':False}},
-      'url_unittests': {'resultdb':{'enable':False}},
+      'absl_hardening_tests': {},
+      'base_unittests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'components_unittests': {},
+      'crypto_unittests': {},
+      'gfx_unittests': {},
+      'google_apis_unittests': {},
+      'ios_chrome_unittests': {},
+      'ios_net_unittests': {},
+      'ios_web_inttests': {},
+      'ios_web_unittests': {},
+      'ios_web_view_inttests': {},
+      'net_unittests': {},
+      'skia_unittests': {},
+      'sql_unittests': {},
+      'ui_base_unittests': {},
+      'url_unittests': {},
     },
 
     'ios_common_tests': {
-      'absl_hardening_tests': {'resultdb':{'enable':False}},
-      'boringssl_crypto_tests': {'resultdb':{'enable':False}},
-      'boringssl_ssl_tests': {'resultdb':{'enable':False}},
-      'crypto_unittests': {'resultdb':{'enable':False}},
-      'google_apis_unittests': {'resultdb':{'enable':False}},
-      'ios_components_unittests': {'resultdb':{'enable':False}},
-      'ios_net_unittests': {'resultdb':{'enable':False}},
-      'ios_remoting_unittests': {'resultdb':{'enable':False}},
-      'ios_testing_unittests': {'resultdb':{'enable':False}},
-      'net_unittests': {'resultdb':{'enable':False}},
-      'services_unittests': {'resultdb':{'enable':False}},
-      'sql_unittests': {'resultdb':{'enable':False}},
-      'url_unittests': {'resultdb':{'enable':False}},
+      'absl_hardening_tests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'crypto_unittests': {},
+      'google_apis_unittests': {},
+      'ios_components_unittests': {},
+      'ios_net_unittests': {},
+      'ios_remoting_unittests': {},
+      'ios_testing_unittests': {},
+      'net_unittests': {},
+      'services_unittests': {},
+      'sql_unittests': {},
+      'url_unittests': {},
     },
 
     'ios_cronet_tests': {
-      'cronet_test': {'resultdb':{'enable':False}},
+      'cronet_test': {},
     },
 
     'ios_eg2_cq_tests': {
@@ -3663,48 +3663,39 @@
         'swarming': {
           'shards': 3,
         },
-        'resultdb': {
-          'enable': False,
-        },
       },
-      'ios_chrome_signin_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_chrome_signin_eg2tests_module': {},
       'ios_chrome_ui_eg2tests_module': {
         'swarming': {
           'shards': 5,
         },
-        'resultdb': {
-          'enable': False,
-        },
       },
-      'ios_web_shell_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_web_shell_eg2tests_module': {},
     },
 
     'ios_eg2_tests': {
-      'ios_chrome_bookmarks_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_chrome_bookmarks_eg2tests_module': {},
       'ios_chrome_settings_eg2tests_module': {
         'swarming': {
           'shards': 3,
         },
-        'resultdb': {
-          'enable': False,
-        },
       },
-      'ios_chrome_smoke_eg2tests_module': {'resultdb':{'enable':False}},
-      'ios_chrome_web_eg2tests_module': {'resultdb':{'enable':False}},
-      'ios_showcase_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_chrome_smoke_eg2tests_module': {},
+      'ios_chrome_web_eg2tests_module': {},
+      'ios_showcase_eg2tests_module': {},
     },
 
     'ios_screen_size_dependent_tests': {
-      'base_unittests': {'resultdb':{'enable':False}},
-      'components_unittests': {'resultdb':{'enable':False}},
-      'gfx_unittests': {'resultdb':{'enable':False}},
-      'ios_chrome_unittests': {'resultdb':{'enable':False}},
-      'ios_web_inttests': {'resultdb':{'enable':False}},
-      'ios_web_unittests': {'resultdb':{'enable':False}},
-      'ios_web_view_inttests': {'resultdb':{'enable':False}},
-      'ios_web_view_unittests': {'resultdb':{'enable':False}},
-      'skia_unittests': {'resultdb':{'enable':False}},
-      'ui_base_unittests': {'resultdb':{'enable':False}},
+      'base_unittests': {},
+      'components_unittests': {},
+      'gfx_unittests': {},
+      'ios_chrome_unittests': {},
+      'ios_web_inttests': {},
+      'ios_web_unittests': {},
+      'ios_web_view_inttests': {},
+      'ios_web_view_unittests': {},
+      'skia_unittests': {},
+      'ui_base_unittests': {},
     },
 
     # END tests which run on the GPU bots
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 63cd9dd..f2b5b5ef3 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2362,7 +2362,6 @@
       },
       'ios-asan': {
         'mixins': [
-          'enable_resultdb',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -2375,7 +2374,6 @@
       },
       'ios-simulator-code-coverage': {
         'mixins': [
-          'enable_resultdb',
           'ios_output_disabled_tests',
           'isolate_profile_data',
           'mac_10.15',
@@ -2403,7 +2401,6 @@
       },
       'ios-simulator-cronet': {
         'mixins': [
-          'enable_resultdb',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -2429,7 +2426,6 @@
       },
       'ios-simulator-multi-window': {
         'mixins': [
-          'enable_resultdb',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -2442,7 +2438,6 @@
       },
       'ios-webkit-tot': {
         'mixins': [
-          'enable_resultdb',
           'ios_custom_webkit',
           'mac_10.15',
           'mac_toolchain',
@@ -2476,7 +2471,6 @@
           'all',
         ],
         'mixins': [
-          'enable_resultdb',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -2494,7 +2488,6 @@
           'all',
         ],
         'mixins': [
-          'enable_resultdb',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -5367,6 +5360,40 @@
           ]
         },
       },
+      'win7(32)-updater-tester-dbg': {
+        'mixins': [
+          'win7',
+          'x86-32'
+        ],
+        'test_suites': {
+          'gtest_tests': 'updater_gtests',
+          'isolated_scripts': 'updater_isolated_scripts',
+        },
+        'swarming': {
+          'dimension_sets': [
+            {
+              'integrity': 'high',
+            }
+          ]
+        },
+      },
+      'win7(32)-updater-tester-rel': {
+        'mixins': [
+          'win7',
+          'x86-32'
+        ],
+        'test_suites': {
+          'gtest_tests': 'updater_gtests',
+          'isolated_scripts': 'updater_isolated_scripts',
+        },
+        'swarming': {
+          'dimension_sets': [
+            {
+              'integrity': 'high',
+            }
+          ]
+        },
+      },
       'win7-updater-tester-dbg': {
         'mixins': [
           'win7',
diff --git a/third_party/blink/common/mediastream/media_devices.cc b/third_party/blink/common/mediastream/media_devices.cc
index f8efd74..aba52e27 100644
--- a/third_party/blink/common/mediastream/media_devices.cc
+++ b/third_party/blink/common/mediastream/media_devices.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/public/common/mediastream/media_devices.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-shared.h"
 
 namespace blink {
 
@@ -18,7 +19,7 @@
     const std::string& label,
     const std::string& group_id,
     const media::VideoCaptureControlSupport& video_control_support,
-    media::VideoFacingMode video_facing)
+    blink::mojom::FacingMode video_facing)
     : device_id(device_id),
       label(label),
       group_id(group_id),
@@ -30,7 +31,7 @@
     : device_id(descriptor.device_id),
       label(descriptor.GetNameAndModel()),
       video_control_support(descriptor.control_support()),
-      video_facing(descriptor.facing) {}
+      video_facing(static_cast<blink::mojom::FacingMode>(descriptor.facing)) {}
 
 WebMediaDeviceInfo::~WebMediaDeviceInfo() = default;
 
diff --git a/third_party/blink/common/mediastream/media_devices_mojom_traits.cc b/third_party/blink/common/mediastream/media_devices_mojom_traits.cc
index f39b9760..8e7b209 100644
--- a/third_party/blink/common/mediastream/media_devices_mojom_traits.cc
+++ b/third_party/blink/common/mediastream/media_devices_mojom_traits.cc
@@ -9,45 +9,6 @@
 namespace mojo {
 
 // static
-blink::mojom::FacingMode
-EnumTraits<blink::mojom::FacingMode, media::VideoFacingMode>::ToMojom(
-    media::VideoFacingMode facing_mode) {
-  switch (facing_mode) {
-    case media::MEDIA_VIDEO_FACING_NONE:
-      return blink::mojom::FacingMode::NONE;
-    case media::MEDIA_VIDEO_FACING_USER:
-      return blink::mojom::FacingMode::USER;
-    case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
-      return blink::mojom::FacingMode::ENVIRONMENT;
-    default:
-      break;
-  }
-  NOTREACHED();
-  return blink::mojom::FacingMode::NONE;
-}
-
-// static
-bool EnumTraits<blink::mojom::FacingMode, media::VideoFacingMode>::FromMojom(
-    blink::mojom::FacingMode input,
-    media::VideoFacingMode* out) {
-  switch (input) {
-    case blink::mojom::FacingMode::NONE:
-      *out = media::MEDIA_VIDEO_FACING_NONE;
-      return true;
-    case blink::mojom::FacingMode::USER:
-      *out = media::MEDIA_VIDEO_FACING_USER;
-      return true;
-    case blink::mojom::FacingMode::ENVIRONMENT:
-      *out = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
-      return true;
-    default:
-      break;
-  }
-  NOTREACHED();
-  return false;
-}
-
-// static
 bool StructTraits<blink::mojom::MediaDeviceInfoDataView,
                   blink::WebMediaDeviceInfo>::
     Read(blink::mojom::MediaDeviceInfoDataView input,
diff --git a/third_party/blink/common/mediastream/media_devices_unittest.cc b/third_party/blink/common/mediastream/media_devices_unittest.cc
index 8281d92..4ec2ccd 100644
--- a/third_party/blink/common/mediastream/media_devices_unittest.cc
+++ b/third_party/blink/common/mediastream/media_devices_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/public/common/mediastream/media_devices.h"
 #include "media/audio/audio_device_description.h"
+#include "media/base/video_facing.h"
 #include "media/capture/video/video_capture_device_descriptor.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -26,7 +27,8 @@
             device_info.video_control_support.tilt);
   EXPECT_EQ(descriptor.control_support().zoom,
             device_info.video_control_support.zoom);
-  EXPECT_EQ(descriptor.facing, device_info.video_facing);
+  EXPECT_EQ(static_cast<blink::mojom::FacingMode>(descriptor.facing),
+            device_info.video_facing);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
index 00d6a8f..43f2f2db 100644
--- a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
+++ b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
@@ -6,6 +6,7 @@
 
 #include "base/check_op.h"
 #include "media/base/ipc/media_param_traits.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "media/capture/mojom/video_capture_types_mojom_traits.h"
 #include "media/mojo/mojom/display_media_information.mojom.h"
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
diff --git a/third_party/blink/public/common/mediastream/media_devices.h b/third_party/blink/public/common/mediastream/media_devices.h
index b56710e..5719648 100644
--- a/third_party/blink/public/common/mediastream/media_devices.h
+++ b/third_party/blink/public/common/mediastream/media_devices.h
@@ -26,7 +26,7 @@
       const std::string& group_id,
       const media::VideoCaptureControlSupport& video_control_support =
           media::VideoCaptureControlSupport(),
-      media::VideoFacingMode video_facing = media::MEDIA_VIDEO_FACING_NONE);
+      blink::mojom::FacingMode video_facing = blink::mojom::FacingMode::NONE);
   explicit WebMediaDeviceInfo(
       const media::VideoCaptureDeviceDescriptor& descriptor);
   ~WebMediaDeviceInfo();
@@ -37,8 +37,7 @@
   std::string label;
   std::string group_id;
   media::VideoCaptureControlSupport video_control_support;
-  media::VideoFacingMode video_facing =
-      media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
+  blink::mojom::FacingMode video_facing = blink::mojom::FacingMode::NONE;
 };
 
 using WebMediaDeviceInfoArray = std::vector<WebMediaDeviceInfo>;
diff --git a/third_party/blink/public/common/mediastream/media_devices_mojom_traits.h b/third_party/blink/public/common/mediastream/media_devices_mojom_traits.h
index 44c8f77..5efa8a9 100644
--- a/third_party/blink/public/common/mediastream/media_devices_mojom_traits.h
+++ b/third_party/blink/public/common/mediastream/media_devices_mojom_traits.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MEDIASTREAM_MEDIA_DEVICES_MOJOM_TRAITS_H_
 #define THIRD_PARTY_BLINK_PUBLIC_COMMON_MEDIASTREAM_MEDIA_DEVICES_MOJOM_TRAITS_H_
 
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/mediastream/media_devices.h"
 #include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
@@ -12,15 +13,6 @@
 namespace mojo {
 
 template <>
-struct BLINK_COMMON_EXPORT
-    EnumTraits<blink::mojom::FacingMode, media::VideoFacingMode> {
-  static blink::mojom::FacingMode ToMojom(media::VideoFacingMode facing_mode);
-
-  static bool FromMojom(blink::mojom::FacingMode input,
-                        media::VideoFacingMode* out);
-};
-
-template <>
 struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::MediaDeviceInfoDataView,
                                         blink::WebMediaDeviceInfo> {
   static const std::string& device_id(const blink::WebMediaDeviceInfo& info) {
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 98e97ad..d994ecc 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -338,10 +338,6 @@
           mojom = "blink.mojom.MediaDeviceInfo"
           cpp = "::blink::WebMediaDeviceInfo"
         },
-        {
-          mojom = "blink.mojom.FacingMode"
-          cpp = "::media::VideoFacingMode"
-        },
       ]
       traits_headers = [ "//third_party/blink/public/common/mediastream/media_devices_mojom_traits.h" ]
     },
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index f56622c..caa9d56 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3059,6 +3059,9 @@
   kAddEventListenerWithAbortSignal = 3730,
   kXRSessionRequestLightProbe = 3731,
   kBeforematchRevealedHiddenMatchable = 3732,
+  kAddSourceBufferUsingConfig = 3733,
+  kChangeTypeUsingConfig = 3734,
+  kV8SourceBuffer_AppendEncodedChunks_Method = 3735,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/web/web_frame_widget.h b/third_party/blink/public/web/web_frame_widget.h
index 92a70f0..727b67b7 100644
--- a/third_party/blink/public/web/web_frame_widget.h
+++ b/third_party/blink/public/web/web_frame_widget.h
@@ -212,9 +212,9 @@
 
  private:
   // This private constructor and the class/friend declaration ensures that
-  // WebFrameWidgetBase is the only concrete subclass that implements
-  // WebFrameWidget, so that it is safe to downcast to WebFrameWidgetBase.
-  friend class WebFrameWidgetBase;
+  // WebFrameWidgetImpl is the only concrete subclass that implements
+  // WebFrameWidget, so that it is safe to downcast to WebFrameWidgetImpl.
+  friend class WebFrameWidgetImpl;
   WebFrameWidget() = default;
 };
 
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 1c847bae..64541df 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -749,6 +749,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sensor_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_share_data.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_share_data.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_spatial_sensor_options.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_spatial_sensor_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_speech_recognition_error_event_init.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index c23e034..95eb410 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -363,6 +363,7 @@
           "//third_party/blink/renderer/modules/mediasource/html_video_element_media_source.idl",
           "//third_party/blink/renderer/modules/mediasource/media_source.idl",
           "//third_party/blink/renderer/modules/mediasource/source_buffer.idl",
+          "//third_party/blink/renderer/modules/mediasource/source_buffer_config.idl",
           "//third_party/blink/renderer/modules/mediasource/source_buffer_list.idl",
           "//third_party/blink/renderer/modules/mediasource/track_default.idl",
           "//third_party/blink/renderer/modules/mediasource/track_default_list.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/generated.gni b/third_party/blink/renderer/bindings/modules/v8/generated.gni
index 1641dbd..9ee4be94 100644
--- a/third_party/blink/renderer/bindings/modules/v8/generated.gni
+++ b/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -49,6 +49,10 @@
   "$bindings_modules_v8_output_dir/double_or_dom_point.cc",
   "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.cc",
   "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.h",
+  "$bindings_modules_v8_output_dir/encoded_audio_chunk_or_encoded_video_chunk.cc",
+  "$bindings_modules_v8_output_dir/encoded_audio_chunk_or_encoded_video_chunk.h",
+  "$bindings_modules_v8_output_dir/encoded_av_chunk_sequence_or_encoded_av_chunk.cc",
+  "$bindings_modules_v8_output_dir/encoded_av_chunk_sequence_or_encoded_av_chunk.h",
   "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.cc",
   "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.h",
   "$bindings_modules_v8_output_dir/gpu_buffer_or_array_buffer.cc",
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
index 931347f..c5d64e0c 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
@@ -230,4 +230,7 @@
     # modules/beacon/navigator_beacon.idl
     'ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString':
     'ReadableStreamOrXMLHttpRequestBodyInit',
+    # modules/mediasource/source_buffer.idl
+    'EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk':
+    'EncodedAVChunkSequenceOrEncodedAVChunk',
 }
diff --git a/third_party/blink/renderer/bindings/scripts/utilities.py b/third_party/blink/renderer/bindings/scripts/utilities.py
index af664e0..55ac346 100644
--- a/third_party/blink/renderer/bindings/scripts/utilities.py
+++ b/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -497,6 +497,9 @@
         # modules/beacon/navigator_beacon.idl
         'ReadableStreamOrBlobOrArrayBufferOrArrayBufferViewOrFormDataOrURLSearchParamsOrUSVString':
         'ReadableStreamOrXMLHttpRequestBodyInit',
+        # modules/mediasource/source_buffer.idl
+        'EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk':
+        'EncodedAVChunkSequenceOrEncodedAVChunk',
     }
 
     idl_type = union_type
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 69121bf0..593c6746 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -56,7 +56,6 @@
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
diff --git a/third_party/blink/renderer/core/editing/frame_caret_test.cc b/third_party/blink/renderer/core/editing/frame_caret_test.cc
index 3fbd4417..6231f23 100644
--- a/third_party/blink/renderer/core/editing/frame_caret_test.cc
+++ b/third_party/blink/renderer/core/editing/frame_caret_test.cc
@@ -92,8 +92,7 @@
   outer->focus();
   UpdateAllLifecyclePhasesForTest();
   const SelectionInDOMTree& selection = Selection().GetSelectionInDOMTree();
-  EXPECT_EQ(selection.Base(),
-            Position(input, PositionAnchorType::kBeforeChildren));
+  EXPECT_EQ(selection.Base(), Position::FirstPositionInNode(*input));
   EXPECT_FALSE(ShouldShowCaret(caret));
 }
 
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
index 31325c2..9600c06 100644
--- a/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
+++ b/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
@@ -337,14 +337,14 @@
       GetDocument(), "host", shadow_content);
   Node* outer_div = GetDocument().getElementById("outer");
   Node* span_in_shadow = shadow_root->firstChild();
-  Position start(span_in_shadow, PositionAnchorType::kBeforeChildren);
+  Position start = Position::FirstPositionInNode(*span_in_shadow);
   Position end(outer_div, PositionAnchorType::kAfterChildren);
   EXPECT_EQ(
       "[ shadow][text][ iterator.]",
       IteratePartial<DOMTree>(start, end, EntersOpenShadowRootsBehavior()));
 
-  PositionInFlatTree start_in_flat_tree(span_in_shadow,
-                                        PositionAnchorType::kBeforeChildren);
+  PositionInFlatTree start_in_flat_tree =
+      PositionInFlatTree::FirstPositionInNode(*span_in_shadow);
   PositionInFlatTree end_in_flat_tree(outer_div,
                                       PositionAnchorType::kAfterChildren);
   EXPECT_EQ("[text][ shadow][ iterator.]",
@@ -362,14 +362,14 @@
       GetDocument(), "host", shadow_content);
   Node* outer_div = GetDocument().getElementById("outer");
   Node* span_in_shadow = shadow_root->firstChild();
-  Position start(outer_div, PositionAnchorType::kBeforeChildren);
+  Position start = Position::FirstPositionInNode(*outer_div);
   Position end(span_in_shadow, PositionAnchorType::kAfterChildren);
   EXPECT_EQ(
       "[Hello, ][ shadow]",
       IteratePartial<DOMTree>(start, end, EntersOpenShadowRootsBehavior()));
 
-  PositionInFlatTree start_in_flat_tree(outer_div,
-                                        PositionAnchorType::kBeforeChildren);
+  PositionInFlatTree start_in_flat_tree =
+      PositionInFlatTree::FirstPositionInNode(*outer_div);
   PositionInFlatTree end_in_flat_tree(span_in_shadow,
                                       PositionAnchorType::kAfterChildren);
   EXPECT_EQ("[Hello, ][text][ shadow]",
diff --git a/third_party/blink/renderer/core/editing/position.cc b/third_party/blink/renderer/core/editing/position.cc
index 83199ae9..ffa65eb4 100644
--- a/third_party/blink/renderer/core/editing/position.cc
+++ b/third_party/blink/renderer/core/editing/position.cc
@@ -660,7 +660,7 @@
     case PositionAnchorType::kAfterAnchor:
       return Position::AfterNode(*anchor_node);
     case PositionAnchorType::kBeforeChildren:
-      return Position(anchor_node, PositionAnchorType::kBeforeChildren);
+      return Position::FirstPositionInNode(*anchor_node);
     case PositionAnchorType::kBeforeAnchor:
       return Position::BeforeNode(*anchor_node);
     case PositionAnchorType::kOffsetInAnchor: {
@@ -671,7 +671,7 @@
       if (child)
         return Position(child->parentNode(), child->NodeIndex());
       if (!position.OffsetInContainerNode())
-        return Position(anchor_node, PositionAnchorType::kBeforeChildren);
+        return Position::FirstPositionInNode(*anchor_node);
 
       // |child| is null when the position is at the end of the children.
       // <div>foo|</div>
diff --git a/third_party/blink/renderer/core/editing/position_test.cc b/third_party/blink/renderer/core/editing/position_test.cc
index 890d06f..58f0a6f8 100644
--- a/third_party/blink/renderer/core/editing/position_test.cc
+++ b/third_party/blink/renderer/core/editing/position_test.cc
@@ -198,9 +198,8 @@
   EXPECT_EQ(PositionInFlatTree(host, PositionAnchorType::kAfterChildren),
             ToPositionInFlatTree(
                 Position(shadow_root, PositionAnchorType::kAfterChildren)));
-  EXPECT_EQ(PositionInFlatTree(host, PositionAnchorType::kBeforeChildren),
-            ToPositionInFlatTree(
-                Position(shadow_root, PositionAnchorType::kBeforeChildren)));
+  EXPECT_EQ(PositionInFlatTree::FirstPositionInNode(*host),
+            ToPositionInFlatTree(Position::FirstPositionInNode(*shadow_root)));
 }
 
 TEST_F(PositionTest,
diff --git a/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer_test.cc b/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer_test.cc
index 62bb40ef..406d49bce 100644
--- a/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer_test.cc
+++ b/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer_test.cc
@@ -44,8 +44,8 @@
 template <typename Strategy>
 std::string StyledMarkupSerializerTest::Serialize(
     const CreateMarkupOptions& options) {
-  PositionTemplate<Strategy> start = PositionTemplate<Strategy>(
-      GetDocument().body(), PositionAnchorType::kBeforeChildren);
+  PositionTemplate<Strategy> start =
+      PositionTemplate<Strategy>::FirstPositionInNode(*GetDocument().body());
   PositionTemplate<Strategy> end = PositionTemplate<Strategy>(
       GetDocument().body(), PositionAnchorType::kAfterChildren);
   return CreateMarkup(start, end, options).Utf8();
diff --git a/third_party/blink/renderer/core/editing/substring_util.h b/third_party/blink/renderer/core/editing/substring_util.h
index e0babc53..362edfe 100644
--- a/third_party/blink/renderer/core/editing/substring_util.h
+++ b/third_party/blink/renderer/core/editing/substring_util.h
@@ -46,17 +46,17 @@
 }  // namespace gfx
 
 namespace blink {
-class WebFrameWidgetBase;
+class WebFrameWidgetImpl;
 class LocalFrame;
 
 class SubstringUtil {
  public:
   // Returns an autoreleased NSAttributedString that is the word under
-  // the given point inside the given WebFrameWidgetBase or nil on error.
+  // the given point inside the given WebFrameWidgetImpl or nil on error.
   // Upon return, |baselinePoint| is set to the left baseline point in
   // AppKit coordinates.
   CORE_EXPORT static NSAttributedString* AttributedWordAtPoint(
-      WebFrameWidgetBase*,
+      WebFrameWidgetImpl*,
       gfx::Point,
       gfx::Point& baseline_point);
 
diff --git a/third_party/blink/renderer/core/editing/substring_util.mm b/third_party/blink/renderer/core/editing/substring_util.mm
index e27858a..49acf21 100644
--- a/third_party/blink/renderer/core/editing/substring_util.mm
+++ b/third_party/blink/renderer/core/editing/substring_util.mm
@@ -48,7 +48,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -153,7 +153,7 @@
 }  // namespace
 
 NSAttributedString* SubstringUtil::AttributedWordAtPoint(
-    WebFrameWidgetBase* frame_widget,
+    WebFrameWidgetImpl* frame_widget,
     gfx::Point point,
     gfx::Point& baseline_point) {
   HitTestResult result =
diff --git a/third_party/blink/renderer/core/editing/substring_util_test.mm b/third_party/blink/renderer/core/editing/substring_util_test.mm
index 311a827..6a5d38f 100644
--- a/third_party/blink/renderer/core/editing/substring_util_test.mm
+++ b/third_party/blink/renderer/core/editing/substring_util_test.mm
@@ -10,7 +10,7 @@
 #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
diff --git a/third_party/blink/renderer/core/events/current_input_event.h b/third_party/blink/renderer/core/events/current_input_event.h
index 9cf5880..faf00d1 100644
--- a/third_party/blink/renderer/core/events/current_input_event.h
+++ b/third_party/blink/renderer/core/events/current_input_event.h
@@ -22,7 +22,7 @@
   static const WebInputEvent* Get() { return current_input_event_; }
 
  private:
-  friend class WebFrameWidgetBase;
+  friend class WebFrameWidgetImpl;
   friend class NavigationPolicyTest;
 
   static const WebInputEvent* current_input_event_;
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 89cddd09..9ae01a2 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -50,7 +50,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
 #include "third_party/blink/renderer/core/inspector/devtools_agent.h"
@@ -159,7 +159,7 @@
     agent->FlushProtocolNotifications();
 
     // 1. Disable input events.
-    WebFrameWidgetBase::SetIgnoreInputEvents(true);
+    WebFrameWidgetImpl::SetIgnoreInputEvents(true);
     for (auto* const view : WebViewImpl::AllInstances())
       view->GetChromeClient().NotifyPopupOpeningObservers();
 
@@ -192,7 +192,7 @@
     // code, but it is moved here to support browser-side navigation.
     message_loop_->QuitNow();
     page_pauser_.reset();
-    WebFrameWidgetBase::SetIgnoreInputEvents(false);
+    WebFrameWidgetImpl::SetIgnoreInputEvents(false);
   }
 
   bool running_for_debug_break_;
diff --git a/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc b/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
index baca3c4a..4956dfb 100644
--- a/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
@@ -15,8 +15,8 @@
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/html_element_type_helpers.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
 #include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index a04d8bf9..2da68d2 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -54,8 +54,8 @@
 #include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
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 620c124..391667f6 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -115,10 +115,9 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/viewport_data.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
@@ -1147,7 +1146,7 @@
   if (!main_frame)
     return;
 
-  WebFrameWidgetBase* widget = main_frame->LocalRootFrameWidget();
+  WebFrameWidgetImpl* widget = main_frame->LocalRootFrameWidget();
   widget->SetBrowserControlsShownRatio(GetBrowserControls().TopShownRatio(),
                                        GetBrowserControls().BottomShownRatio());
   widget->SetBrowserControlsParams(GetBrowserControls().Params());
@@ -1290,7 +1289,7 @@
   // Since we updated the override value, notify all widgets.
   for (WebFrame* frame = MainFrame(); frame; frame = frame->TraverseNext()) {
     if (frame->IsWebLocalFrame()) {
-      if (WebFrameWidgetBase* widget = static_cast<WebFrameWidgetBase*>(
+      if (WebFrameWidgetImpl* widget = static_cast<WebFrameWidgetImpl*>(
               frame->ToWebLocalFrame()->FrameWidget()))
         widget->UpdateScreenInfo(widget->GetScreenInfo());
     }
@@ -1319,7 +1318,8 @@
   fullscreen_controller_->DidExitFullscreen();
 }
 
-void WebViewImpl::SetMainFrameViewWidget(WebViewFrameWidget* widget) {
+void WebViewImpl::SetMainFrameViewWidget(WebFrameWidgetImpl* widget) {
+  DCHECK(!widget || widget->ForMainFrame());
   web_widget_ = widget;
 }
 
@@ -1333,7 +1333,7 @@
   UpdateTargetURL(focus_url_, mouse_over_url_);
 }
 
-WebViewFrameWidget* WebViewImpl::MainFrameViewWidget() {
+WebFrameWidgetImpl* WebViewImpl::MainFrameViewWidget() {
   return web_widget_;
 }
 
@@ -2378,7 +2378,7 @@
   // Note that the TextInputState itself is cleared when we clear the focus,
   // but no updates to the browser will be triggered until the next animation
   // frame, which won't happen if we're freezing the page.
-  if (auto* widget = static_cast<WebFrameWidgetBase*>(
+  if (auto* widget = static_cast<WebFrameWidgetImpl*>(
           focused_frame->GetWidgetForLocalRoot())) {
     widget->FinishComposingText(false /* keep_selection */);
     widget->UpdateTextInputState();
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 7b946f0..7c9e811 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -94,7 +94,7 @@
 class WebLocalFrameImpl;
 class WebSettingsImpl;
 class WebViewClient;
-class WebViewFrameWidget;
+class WebFrameWidgetImpl;
 
 enum class FullscreenRequestType;
 
@@ -480,8 +480,8 @@
   // limit.
   void SetMaximumLegibleScale(float);
 
-  void SetMainFrameViewWidget(WebViewFrameWidget* widget);
-  WebViewFrameWidget* MainFrameViewWidget();
+  void SetMainFrameViewWidget(WebFrameWidgetImpl* widget);
+  WebFrameWidgetImpl* MainFrameViewWidget();
 
   // Called when hovering over an anchor with the given URL.
   void SetMouseOverURL(const KURL&);
@@ -542,11 +542,8 @@
   friend class frame_test_helpers::WebViewHelper;
   friend class SimCompositor;
   friend class WebView;  // So WebView::Create can call our constructor
-  friend class WebViewFrameWidget;
   friend class WTF::RefCounted<WebViewImpl>;
 
-  // These are temporary methods to allow WebViewFrameWidget to delegate to
-  // WebViewImpl. We expect to eventually move these out.
   void ThemeChanged();
 
   // Update the target url locally and tell the browser that the target URL has
@@ -785,7 +782,7 @@
 
   // The WebWidget for the main frame. This is expected to be unset when the
   // WebWidget destroys itself. This will be null if the main frame is remote.
-  WeakPersistent<WebViewFrameWidget> web_widget_;
+  WeakPersistent<WebFrameWidgetImpl> web_widget_;
 
   // We defer commits when transitioning to a new page. ChromeClientImpl calls
   // StopDeferringCommits() to release this when a new page is loaded.
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 9b491bb..5f18592 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -103,7 +103,6 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
diff --git a/third_party/blink/renderer/core/frame/DEPS b/third_party/blink/renderer/core/frame/DEPS
index 3ebe612..88ccea2 100644
--- a/third_party/blink/renderer/core/frame/DEPS
+++ b/third_party/blink/renderer/core/frame/DEPS
@@ -33,10 +33,10 @@
   "visual_viewport\.cc": [
     "+cc/layers/solid_color_scrollbar_layer.h",
   ],
-  "web_frame_widget_base\.cc": [
+  "web_frame_widget_impl\.cc": [
     "+cc/trees/swap_promise.h",
   ],
-  "web_frame_widget_base\.h": [
+  "web_frame_widget_impl\.h": [
     "+services/viz/public/mojom/hit_test/input_target_client.mojom-blink.h",
     "+ui/base/mojom/ui_base_types.mojom-shared.h",
   ],
diff --git a/third_party/blink/renderer/core/frame/build.gni b/third_party/blink/renderer/core/frame/build.gni
index 9c16421..aea259f6 100644
--- a/third_party/blink/renderer/core/frame/build.gni
+++ b/third_party/blink/renderer/core/frame/build.gni
@@ -209,8 +209,6 @@
   "local_frame_client_impl.cc",
   "local_frame_client_impl.h",
   "web_frame.cc",
-  "web_frame_widget_base.cc",
-  "web_frame_widget_base.h",
   "web_frame_widget_impl.cc",
   "web_frame_widget_impl.h",
   "web_local_frame_impl.cc",
@@ -218,8 +216,6 @@
   "web_remote_frame_impl.cc",
   "web_local_frame_client.cc",
   "web_remote_frame_impl.h",
-  "web_view_frame_widget.cc",
-  "web_view_frame_widget.h",
   "window_event_handlers.h",
   "window_or_worker_global_scope.cc",
   "window_or_worker_global_scope.h",
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 627e1da..173c59d 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -59,7 +59,6 @@
 #include "third_party/blink/public/web/web_navigation_params.h"
 #include "third_party/blink/public/web/web_settings.h"
 #include "third_party/blink/public/web/web_view_client.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -481,7 +480,7 @@
   // the case by this point).
   web_view_->DidAttachLocalMainFrame();
 
-  static_cast<WebFrameWidgetBase*>(widget)->UpdateScreenInfo(
+  static_cast<WebFrameWidgetImpl*>(widget)->UpdateScreenInfo(
       test_web_widget_client_->GetInitialScreenInfo());
 
   // Set an initial size for subframes.
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index e625f242..20d699e 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -64,7 +64,7 @@
 #include "third_party/blink/public/web/web_view_client.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
 #include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h"
 #include "third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h"
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index abe3660..f9be9194 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -120,7 +120,7 @@
 #include "third_party/blink/renderer/core/frame/user_activation.h"
 #include "third_party/blink/renderer/core/frame/virtual_keyboard_overlay_changed_observer.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h"
 #include "third_party/blink/renderer/core/html/html_frame_element_base.h"
@@ -1788,7 +1788,7 @@
   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(this);
   if (!web_frame)
     return nullptr;
-  // This WebFrameWidgetBase upcasts to a FrameWidget which is the interface
+  // This WebFrameWidgetImpl upcasts to a FrameWidget which is the interface
   // exposed to Blink core.
   return web_frame->LocalRootFrameWidget();
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
index 3cc00957..91a1a67 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -73,7 +73,7 @@
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/html_frame_element_base.h"
diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.cc b/third_party/blink/renderer/core/frame/remote_frame_owner.cc
index 70e5b40..33ffce5 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_owner.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame_owner.cc
@@ -9,7 +9,7 @@
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
diff --git a/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc b/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
index 76121e4..1b670e7 100644
--- a/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
+++ b/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
@@ -6,12 +6,12 @@
 
 #include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/common/widget/visual_properties.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 
 namespace blink {
 
 ScreenMetricsEmulator::ScreenMetricsEmulator(
-    WebFrameWidgetBase* frame_widget,
+    WebFrameWidgetImpl* frame_widget,
     const ScreenInfo& screen_info,
     const gfx::Size& widget_size,
     const gfx::Size& visible_viewport_size,
diff --git a/third_party/blink/renderer/core/frame/screen_metrics_emulator.h b/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
index 674d9951..970d8d85 100644
--- a/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
+++ b/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
@@ -17,15 +17,15 @@
 namespace blink {
 
 struct VisualProperties;
-class WebFrameWidgetBase;
+class WebFrameWidgetImpl;
 
 // ScreenMetricsEmulator class manages screen emulation inside a
-// WebFrameWidgetBase. This includes resizing, placing view on the screen at
+// WebFrameWidgetImpl. This includes resizing, placing view on the screen at
 // desired position, changing device scale factor, and scaling down the whole
 // widget if required to fit into the browser window.
 class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
  public:
-  ScreenMetricsEmulator(WebFrameWidgetBase* frame_widget,
+  ScreenMetricsEmulator(WebFrameWidgetImpl* frame_widget,
                         const ScreenInfo& screen_info,
                         const gfx::Size& widget_size,
                         const gfx::Size& visible_viewport_size,
@@ -55,10 +55,10 @@
   gfx::Point ViewRectOrigin();
 
   // Disables emulation and applies non-emulated values to the
-  // WebFrameWidgetBase. Call this before destroying the ScreenMetricsEmulator.
+  // WebFrameWidgetImpl. Call this before destroying the ScreenMetricsEmulator.
   void DisableAndApply();
 
-  // Sets new parameters and applies them to the WebFrameWidgetBase.
+  // Sets new parameters and applies them to the WebFrameWidgetImpl.
   void ChangeEmulationParams(const DeviceEmulationParams& params);
 
   void UpdateVisualProperties(const VisualProperties& visual_properties);
@@ -77,9 +77,9 @@
   // Applies emulated values to the WidgetBase.
   void Apply();
 
-  Member<WebFrameWidgetBase> const frame_widget_;
+  Member<WebFrameWidgetImpl> const frame_widget_;
 
-  // Parameters as passed by `WebFrameWidgetBase::EnableDeviceEmulation()`
+  // Parameters as passed by `WebFrameWidgetImpl::EnableDeviceEmulation()`
   DeviceEmulationParams emulation_params_;
 
   // Original values to restore back after emulation ends.
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index 03c8dc9..ca2b616 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -31,7 +31,7 @@
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/html_body_element.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index 7dd4c24..946b2a2a 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -140,7 +140,6 @@
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
@@ -3177,7 +3176,7 @@
                                 const gfx::Point& point,
                                 bool ignore_clipping) {
   DCHECK(web_view_impl->MainFrameImpl());
-  WebFrameWidgetBase* widget =
+  WebFrameWidgetImpl* widget =
       web_view_impl->MainFrameImpl()->FrameWidgetImpl();
   DCHECK(widget);
   return widget->ComputeBlockBound(point, ignore_clipping);
@@ -7371,7 +7370,7 @@
   auto intersection_state = blink::mojom::blink::ViewportIntersectionState::New(
       viewport_intersection, mainframe_intersection, gfx::Rect(),
       occlusion_state, gfx::Size(), gfx::Point(), transform);
-  static_cast<WebFrameWidgetBase*>(widget)->SetViewportIntersection(
+  static_cast<WebFrameWidgetImpl*>(widget)->SetViewportIntersection(
       std::move(intersection_state));
   EXPECT_EQ(client.MainFrameIntersection(), blink::WebRect(100, 100, 200, 140));
 }
@@ -13550,7 +13549,7 @@
   blink::mojom::FrameOcclusionState occlusion_state =
       blink::mojom::FrameOcclusionState::kUnknown;
 
-  static_cast<WebFrameWidgetBase*>(widget)->SetViewportIntersection(
+  static_cast<WebFrameWidgetImpl*>(widget)->SetViewportIntersection(
       blink::mojom::blink::ViewportIntersectionState::New(
           viewport_intersection, mainframe_intersection, viewport_intersection,
           occlusion_state, gfx::Size(), gfx::Point(), viewport_transform));
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
deleted file mode 100644
index 9e272ef..0000000
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ /dev/null
@@ -1,4013 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/swap_promise.h"
-#include "cc/trees/ukm_manager.h"
-#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
-#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/web/web_autofill_client.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_local_frame_client.h"
-#include "third_party/blink/public/web/web_performance.h"
-#include "third_party/blink/public/web/web_plugin.h"
-#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/public/web/web_view_client.h"
-#include "third_party/blink/public/web/web_widget_client.h"
-#include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
-#include "third_party/blink/renderer/core/editing/frame_selection.h"
-#include "third_party/blink/renderer/core/events/current_input_event.h"
-#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
-#include "third_party/blink/renderer/core/events/wheel_event.h"
-#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
-#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
-#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
-#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/remote_frame_client.h"
-#include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/html/html_plugin_element.h"
-#include "third_party/blink/renderer/core/html/portal/document_portals.h"
-#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
-#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
-#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/layout/hit_test_location.h"
-#include "third_party/blink/renderer/core/layout/hit_test_request.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
-#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/interactive_detector.h"
-#include "third_party/blink/renderer/core/page/context_menu_controller.h"
-#include "third_party/blink/renderer/core/page/drag_actions.h"
-#include "third_party/blink/renderer/core/page/drag_controller.h"
-#include "third_party/blink/renderer/core/page/drag_data.h"
-#include "third_party/blink/renderer/core/page/focus_controller.h"
-#include "third_party/blink/renderer/core/page/link_highlight.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
-#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
-#include "third_party/blink/renderer/core/page/validation_message_client.h"
-#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
-#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
-#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
-#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
-#include "third_party/blink/renderer/platform/widget/widget_base.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
-#include "ui/gfx/geometry/point_conversions.h"
-
-#if defined(OS_MAC)
-#include "third_party/blink/renderer/core/editing/substring_util.h"
-#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
-#include "ui/base/mojom/attributed_string.mojom-blink.h"
-#include "ui/gfx/geometry/point.h"
-#endif
-
-namespace WTF {
-template <>
-struct CrossThreadCopier<blink::WebReportTimeCallback>
-    : public CrossThreadCopierByValuePassThrough<blink::WebReportTimeCallback> {
-  STATIC_ONLY(CrossThreadCopier);
-};
-
-}  // namespace WTF
-
-namespace blink {
-
-namespace {
-
-const int kCaretPadding = 10;
-const float kIdealPaddingRatio = 0.3f;
-
-// Returns a rect which is offset and scaled accordingly to |base_rect|'s
-// location and size.
-FloatRect NormalizeRect(const IntRect& to_normalize, const IntRect& base_rect) {
-  FloatRect result(to_normalize);
-  result.SetLocation(
-      FloatPoint(to_normalize.Location() + (-base_rect.Location())));
-  result.Scale(1.0 / base_rect.Width(), 1.0 / base_rect.Height());
-  return result;
-}
-
-void ForEachLocalFrameControlledByWidget(
-    LocalFrame* frame,
-    const base::RepeatingCallback<void(WebLocalFrame*)>& callback) {
-  callback.Run(WebLocalFrameImpl::FromFrame(frame));
-  for (Frame* child = frame->FirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->IsLocalFrame()) {
-      ForEachLocalFrameControlledByWidget(DynamicTo<LocalFrame>(child),
-                                          callback);
-    }
-  }
-}
-
-// Iterate the remote children that will be controlled by the widget. Skip over
-// any RemoteFrames have have another LocalFrame root as their parent.
-void ForEachRemoteFrameChildrenControlledByWidget(
-    Frame* frame,
-    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
-  for (Frame* child = frame->Tree().FirstChild(); child;
-       child = child->Tree().NextSibling()) {
-    if (auto* remote_frame = DynamicTo<RemoteFrame>(child)) {
-      callback.Run(remote_frame);
-      ForEachRemoteFrameChildrenControlledByWidget(remote_frame, callback);
-    } else if (auto* local_frame = DynamicTo<LocalFrame>(child)) {
-      // If iteration arrives at a local root then don't descend as it will be
-      // controlled by another widget.
-      if (!local_frame->IsLocalRoot()) {
-        ForEachRemoteFrameChildrenControlledByWidget(local_frame, callback);
-      }
-    }
-  }
-
-  // Iterate on any portals owned by a local frame.
-  if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
-    if (Document* document = local_frame->GetDocument()) {
-      for (PortalContents* portal :
-           DocumentPortals::From(*document).GetPortals()) {
-        if (RemoteFrame* remote_frame = portal->GetFrame())
-          callback.Run(remote_frame);
-      }
-    }
-  }
-}
-
-viz::FrameSinkId GetRemoteFrameSinkId(const HitTestResult& result) {
-  Node* node = result.InnerNode();
-  auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node);
-  if (!frame_owner || !frame_owner->ContentFrame() ||
-      !frame_owner->ContentFrame()->IsRemoteFrame())
-    return viz::FrameSinkId();
-
-  RemoteFrame* remote_frame = To<RemoteFrame>(frame_owner->ContentFrame());
-  if (remote_frame->IsIgnoredForHitTest())
-    return viz::FrameSinkId();
-  LayoutObject* object = result.GetLayoutObject();
-  DCHECK(object);
-  if (!object->IsBox())
-    return viz::FrameSinkId();
-
-  IntPoint local_point = RoundedIntPoint(result.LocalPoint());
-  if (!To<LayoutBox>(object)->ComputedCSSContentBoxRect().Contains(local_point))
-    return viz::FrameSinkId();
-
-  return remote_frame->GetFrameSinkId();
-}
-}  // namespace
-
-bool WebFrameWidgetBase::ignore_input_events_ = false;
-
-WebFrameWidgetBase::WebFrameWidgetBase(
-    WebWidgetClient& client,
-    CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
-        frame_widget_host,
-    CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
-        frame_widget,
-    CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
-        widget_host,
-    CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
-        widget,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    const viz::FrameSinkId& frame_sink_id,
-    bool hidden,
-    bool never_composited,
-    bool is_for_child_local_root,
-    bool is_for_nested_main_frame)
-    : widget_base_(std::make_unique<WidgetBase>(this,
-                                                std::move(widget_host),
-                                                std::move(widget),
-                                                task_runner,
-                                                hidden,
-                                                never_composited,
-                                                is_for_child_local_root)),
-      client_(&client),
-      frame_sink_id_(frame_sink_id),
-      is_for_child_local_root_(is_for_child_local_root),
-      self_keep_alive_(PERSISTENT_FROM_HERE, this) {
-  DCHECK(task_runner);
-  if (is_for_nested_main_frame)
-    main_data().is_for_nested_main_frame = is_for_nested_main_frame;
-  frame_widget_host_.Bind(std::move(frame_widget_host), task_runner);
-  receiver_.Bind(std::move(frame_widget), task_runner);
-}
-
-WebFrameWidgetBase::~WebFrameWidgetBase() {
-  // Ensure that Close is called and we aren't releasing |widget_base_| in the
-  // destructor.
-  // TODO(crbug.com/1139104): This CHECK can be changed to a DCHECK once
-  // the issue is solved.
-  CHECK(!widget_base_);
-}
-
-void WebFrameWidgetBase::BindLocalRoot(WebLocalFrame& local_root) {
-  local_root_ = To<WebLocalFrameImpl>(local_root);
-  local_root_->SetFrameWidget(this);
-  request_animation_after_delay_timer_.reset(
-      new TaskRunnerTimer<WebFrameWidgetBase>(
-          local_root.GetTaskRunner(TaskType::kInternalDefault), this,
-          &WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired));
-}
-
-bool WebFrameWidgetBase::ForTopMostMainFrame() const {
-  return ForMainFrame() && !main_data().is_for_nested_main_frame;
-}
-
-void WebFrameWidgetBase::SetIsNestedMainFrameWidget(bool is_nested) {
-  main_data().is_for_nested_main_frame = is_nested;
-}
-
-void WebFrameWidgetBase::Close(
-    scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
-  LocalFrameView* frame_view;
-  if (is_for_child_local_root_) {
-    frame_view = LocalRootImpl()->GetFrame()->View();
-  } else {
-    // Scrolling for the root frame is special we need to pass null indicating
-    // we are at the top of the tree when setting up the Animation. Which will
-    // cause ownership of the timeline and animation host.
-    // See ScrollingCoordinator::AnimationHostInitialized.
-    frame_view = nullptr;
-  }
-  GetPage()->WillCloseAnimationHost(frame_view);
-
-  if (ForMainFrame()) {
-    // Closing the WebFrameWidgetBase happens in response to the local main
-    // frame being detached from the Page/WebViewImpl.
-    View()->SetMainFrameViewWidget(nullptr);
-  }
-
-  mutator_dispatcher_ = nullptr;
-  local_root_->SetFrameWidget(nullptr);
-  local_root_ = nullptr;
-  client_ = nullptr;
-  request_animation_after_delay_timer_.reset();
-  widget_base_->Shutdown(std::move(cleanup_runner));
-  widget_base_.reset();
-  receiver_.reset();
-  input_target_receiver_.reset();
-  self_keep_alive_.Clear();
-}
-
-WebLocalFrame* WebFrameWidgetBase::LocalRoot() const {
-  return local_root_;
-}
-
-WebRect WebFrameWidgetBase::ComputeBlockBound(
-    const gfx::Point& point_in_root_frame,
-    bool ignore_clipping) const {
-  HitTestLocation location(local_root_->GetFrameView()->ConvertFromRootFrame(
-      PhysicalOffset(IntPoint(point_in_root_frame))));
-  HitTestRequest::HitTestRequestType hit_type =
-      HitTestRequest::kReadOnly | HitTestRequest::kActive |
-      (ignore_clipping ? HitTestRequest::kIgnoreClipping : 0);
-  HitTestResult result =
-      local_root_->GetFrame()->GetEventHandler().HitTestResultAtLocation(
-          location, hit_type);
-  result.SetToShadowHostIfInRestrictedShadowRoot();
-
-  Node* node = result.InnerNodeOrImageMapImage();
-  if (!node)
-    return WebRect();
-
-  // Find the block type node based on the hit node.
-  // FIXME: This wants to walk flat tree with
-  // LayoutTreeBuilderTraversal::parent().
-  while (node &&
-         (!node->GetLayoutObject() || node->GetLayoutObject()->IsInline()))
-    node = LayoutTreeBuilderTraversal::Parent(*node);
-
-  // Return the bounding box in the root frame's coordinate space.
-  if (node) {
-    IntRect absolute_rect = node->GetLayoutObject()->AbsoluteBoundingBoxRect();
-    LocalFrame* frame = node->GetDocument().GetFrame();
-    return frame->View()->ConvertToRootFrame(absolute_rect);
-  }
-  return WebRect();
-}
-
-void WebFrameWidgetBase::DragTargetDragEnter(
-    const WebDragData& web_drag_data,
-    const gfx::PointF& point_in_viewport,
-    const gfx::PointF& screen_point,
-    DragOperationsMask operations_allowed,
-    uint32_t key_modifiers,
-    DragTargetDragEnterCallback callback) {
-  DCHECK(!current_drag_data_);
-
-  current_drag_data_ = DataObject::Create(web_drag_data);
-  operations_allowed_ = operations_allowed;
-
-  blink::DragOperation operation = DragTargetDragEnterOrOver(
-      point_in_viewport, screen_point, kDragEnter, key_modifiers);
-  std::move(callback).Run(operation);
-}
-
-void WebFrameWidgetBase::DragTargetDragOver(
-    const gfx::PointF& point_in_viewport,
-    const gfx::PointF& screen_point,
-    DragOperationsMask operations_allowed,
-    uint32_t key_modifiers,
-    DragTargetDragOverCallback callback) {
-  operations_allowed_ = operations_allowed;
-
-  blink::DragOperation operation = DragTargetDragEnterOrOver(
-      point_in_viewport, screen_point, kDragOver, key_modifiers);
-  std::move(callback).Run(operation);
-}
-
-void WebFrameWidgetBase::DragTargetDragLeave(
-    const gfx::PointF& point_in_viewport,
-    const gfx::PointF& screen_point) {
-  DCHECK(current_drag_data_);
-
-  // TODO(paulmeyer): It shouldn't be possible for |current_drag_data_| to be
-  // null here, but this is somehow happening (rarely). This suggests that in
-  // some cases drag-leave is happening before drag-enter, which should be
-  // impossible. This needs to be investigated further. Once fixed, the extra
-  // check for |!current_drag_data_| should be removed. (crbug.com/671152)
-  if (IgnoreInputEvents() || !current_drag_data_) {
-    CancelDrag();
-    return;
-  }
-
-  gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
-  DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
-                     FloatPoint(screen_point), operations_allowed_);
-
-  GetPage()->GetDragController().DragExited(&drag_data,
-                                            *local_root_->GetFrame());
-
-  // FIXME: why is the drag scroll timer not stopped here?
-
-  drag_operation_ = kDragOperationNone;
-  current_drag_data_ = nullptr;
-}
-
-void WebFrameWidgetBase::DragTargetDrop(const WebDragData& web_drag_data,
-                                        const gfx::PointF& point_in_viewport,
-                                        const gfx::PointF& screen_point,
-                                        uint32_t key_modifiers) {
-  gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
-
-  DCHECK(current_drag_data_);
-  current_drag_data_ = DataObject::Create(web_drag_data);
-
-  // If this webview transitions from the "drop accepting" state to the "not
-  // accepting" state, then our IPC message reply indicating that may be in-
-  // flight, or else delayed by javascript processing in this webview.  If a
-  // drop happens before our IPC reply has reached the browser process, then
-  // the browser forwards the drop to this webview.  So only allow a drop to
-  // proceed if our webview m_dragOperation state is not DragOperationNone.
-
-  if (drag_operation_ == kDragOperationNone) {
-    // IPC RACE CONDITION: do not allow this drop.
-    DragTargetDragLeave(point_in_viewport, screen_point);
-    return;
-  }
-
-  if (!IgnoreInputEvents()) {
-    current_drag_data_->SetModifiers(key_modifiers);
-    DragData drag_data(current_drag_data_.Get(),
-                       FloatPoint(point_in_root_frame),
-                       FloatPoint(screen_point), operations_allowed_);
-
-    GetPage()->GetDragController().PerformDrag(&drag_data,
-                                               *local_root_->GetFrame());
-  }
-  drag_operation_ = kDragOperationNone;
-  current_drag_data_ = nullptr;
-}
-
-void WebFrameWidgetBase::DragSourceEndedAt(const gfx::PointF& point_in_viewport,
-                                           const gfx::PointF& screen_point,
-                                           DragOperation operation) {
-  if (!local_root_) {
-    // We should figure out why |local_root_| could be nullptr
-    // (https://crbug.com/792345).
-    return;
-  }
-
-  if (IgnoreInputEvents()) {
-    CancelDrag();
-    return;
-  }
-  gfx::PointF point_in_root_frame(
-      GetPage()->GetVisualViewport().ViewportToRootFrame(
-          FloatPoint(point_in_viewport)));
-
-  WebMouseEvent fake_mouse_move(
-      WebInputEvent::Type::kMouseMove, point_in_root_frame, screen_point,
-      WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
-      base::TimeTicks::Now());
-  fake_mouse_move.SetFrameScale(1);
-  local_root_->GetFrame()->GetEventHandler().DragSourceEndedAt(fake_mouse_move,
-                                                               operation);
-}
-
-void WebFrameWidgetBase::DragSourceSystemDragEnded() {
-  CancelDrag();
-}
-
-void WebFrameWidgetBase::SetBackgroundOpaque(bool opaque) {
-  if (opaque) {
-    View()->ClearBaseBackgroundColorOverride();
-    View()->ClearBackgroundColorOverride();
-  } else {
-    View()->SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT);
-    View()->SetBackgroundColorOverride(SK_ColorTRANSPARENT);
-  }
-}
-
-void WebFrameWidgetBase::SetTextDirection(base::i18n::TextDirection direction) {
-  LocalFrame* focusedFrame = FocusedLocalFrameInWidget();
-  if (focusedFrame)
-    focusedFrame->SetTextDirection(direction);
-}
-
-void WebFrameWidgetBase::SetInheritedEffectiveTouchActionForSubFrame(
-    TouchAction touch_action) {
-  DCHECK(ForSubframe());
-  LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
-}
-
-void WebFrameWidgetBase::UpdateRenderThrottlingStatusForSubFrame(
-    bool is_throttled,
-    bool subtree_throttled) {
-  DCHECK(ForSubframe());
-  LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
-      is_throttled, subtree_throttled, true);
-}
-
-#if defined(OS_MAC)
-void WebFrameWidgetBase::GetStringAtPoint(const gfx::Point& point_in_local_root,
-                                          GetStringAtPointCallback callback) {
-  gfx::Point baseline_point;
-  ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
-  NSAttributedString* string = SubstringUtil::AttributedWordAtPoint(
-      this, point_in_local_root, baseline_point);
-  if (string)
-    attributed_string = ui::mojom::blink::AttributedString::From(string);
-
-  std::move(callback).Run(std::move(attributed_string), baseline_point);
-}
-#endif
-
-void WebFrameWidgetBase::BindWidgetCompositor(
-    mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
-  widget_base_->BindWidgetCompositor(std::move(receiver));
-}
-
-void WebFrameWidgetBase::BindInputTargetClient(
-    mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver) {
-  DCHECK(!input_target_receiver_.is_bound());
-  input_target_receiver_.Bind(
-      std::move(receiver),
-      local_root_->GetTaskRunner(TaskType::kInternalDefault));
-}
-
-void WebFrameWidgetBase::FrameSinkIdAt(const gfx::PointF& point,
-                                       const uint64_t trace_id,
-                                       FrameSinkIdAtCallback callback) {
-  TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Event.Pipeline",
-                         TRACE_ID_GLOBAL(trace_id),
-                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
-                         "step", "FrameSinkIdAt");
-
-  gfx::PointF local_point;
-  viz::FrameSinkId id = GetFrameSinkIdAtPoint(point, &local_point);
-  std::move(callback).Run(id, local_point);
-}
-
-viz::FrameSinkId WebFrameWidgetBase::GetFrameSinkIdAtPoint(
-    const gfx::PointF& point_in_dips,
-    gfx::PointF* local_point_in_dips) {
-  HitTestResult result =
-      CoreHitTestResultAt(widget_base_->DIPsToBlinkSpace(point_in_dips));
-
-  Node* result_node = result.InnerNode();
-  *local_point_in_dips = gfx::PointF(point_in_dips);
-
-  // TODO(crbug.com/797828): When the node is null the caller may
-  // need to do extra checks. Like maybe update the layout and then
-  // call the hit-testing API. Either way it might be better to have
-  // a DCHECK for the node rather than a null check here.
-  if (!result_node) {
-    return frame_sink_id_;
-  }
-
-  viz::FrameSinkId remote_frame_sink_id = GetRemoteFrameSinkId(result);
-  if (remote_frame_sink_id.is_valid()) {
-    FloatPoint local_point = FloatPoint(result.LocalPoint());
-    LayoutObject* object = result.GetLayoutObject();
-    if (auto* box = DynamicTo<LayoutBox>(object))
-      local_point.MoveBy(-FloatPoint(box->PhysicalContentBoxOffset()));
-
-    *local_point_in_dips =
-        widget_base_->BlinkSpaceToDIPs(gfx::PointF(local_point));
-    return remote_frame_sink_id;
-  }
-
-  // Return the FrameSinkId for the current widget if the point did not hit
-  // test to a remote frame, or the point is outside of the remote frame's
-  // content box, or the remote frame doesn't have a valid FrameSinkId yet.
-  return frame_sink_id_;
-}
-
-gfx::RectF WebFrameWidgetBase::BlinkSpaceToDIPs(const gfx::RectF& rect) {
-  return widget_base_->BlinkSpaceToDIPs(rect);
-}
-
-gfx::Rect WebFrameWidgetBase::BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) {
-  return widget_base_->BlinkSpaceToEnclosedDIPs(rect);
-}
-
-gfx::Size WebFrameWidgetBase::BlinkSpaceToFlooredDIPs(const gfx::Size& size) {
-  return widget_base_->BlinkSpaceToFlooredDIPs(size);
-}
-
-gfx::RectF WebFrameWidgetBase::DIPsToBlinkSpace(const gfx::RectF& rect) {
-  return widget_base_->DIPsToBlinkSpace(rect);
-}
-
-gfx::PointF WebFrameWidgetBase::DIPsToBlinkSpace(const gfx::PointF& point) {
-  return widget_base_->DIPsToBlinkSpace(point);
-}
-
-gfx::Point WebFrameWidgetBase::DIPsToRoundedBlinkSpace(
-    const gfx::Point& point) {
-  return widget_base_->DIPsToRoundedBlinkSpace(point);
-}
-
-float WebFrameWidgetBase::DIPsToBlinkSpace(float scalar) {
-  return widget_base_->DIPsToBlinkSpace(scalar);
-}
-
-gfx::Size WebFrameWidgetBase::DIPsToCeiledBlinkSpace(const gfx::Size& size) {
-  return widget_base_->DIPsToCeiledBlinkSpace(size);
-}
-
-void WebFrameWidgetBase::SetActive(bool active) {
-  View()->SetIsActive(active);
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleKeyEvent(
-    const WebKeyboardEvent& event) {
-  DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
-         (event.GetType() == WebInputEvent::Type::kKeyDown) ||
-         (event.GetType() == WebInputEvent::Type::kKeyUp));
-
-  // Please refer to the comments explaining the m_suppressNextKeypressEvent
-  // member.
-  // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
-  // Webkit. A keyDown event is typically associated with a keyPress(char)
-  // event and a keyUp event. We reset this flag here as this is a new keyDown
-  // event.
-  suppress_next_keypress_event_ = false;
-
-  // If there is a popup open, it should be the one processing the event,
-  // not the page.
-  scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
-  if (page_popup) {
-    page_popup->HandleKeyEvent(event);
-    if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
-      suppress_next_keypress_event_ = true;
-    }
-    return WebInputEventResult::kHandledSystem;
-  }
-
-  auto* frame = DynamicTo<LocalFrame>(FocusedCoreFrame());
-  if (!frame)
-    return WebInputEventResult::kNotHandled;
-
-  WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
-  if (result != WebInputEventResult::kNotHandled) {
-    if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
-      // Suppress the next keypress event unless the focused node is a plugin
-      // node.  (Flash needs these keypress events to handle non-US keyboards.)
-      Element* element = FocusedElement();
-      if (element && element->GetLayoutObject() &&
-          element->GetLayoutObject()->IsEmbeddedObject()) {
-        if (event.windows_key_code == VKEY_TAB) {
-          // If the plugin supports keyboard focus then we should not send a tab
-          // keypress event.
-          WebPluginContainerImpl* plugin_view =
-              To<LayoutEmbeddedContent>(element->GetLayoutObject())->Plugin();
-          if (plugin_view && plugin_view->SupportsKeyboardFocus()) {
-            suppress_next_keypress_event_ = true;
-          }
-        }
-      } else {
-        suppress_next_keypress_event_ = true;
-      }
-    }
-    return result;
-  }
-
-#if !defined(OS_MAC)
-  const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
-#if defined(OS_WIN)
-      WebInputEvent::Type::kKeyUp;
-#else
-      WebInputEvent::Type::kRawKeyDown;
-#endif
-  const WebInputEvent::Type kShiftF10TriggeringEventType =
-      WebInputEvent::Type::kRawKeyDown;
-
-  bool is_unmodified_menu_key =
-      !(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
-      event.windows_key_code == VKEY_APPS;
-  bool is_shift_f10 = (event.GetModifiers() & WebInputEvent::kInputModifiers) ==
-                          WebInputEvent::kShiftKey &&
-                      event.windows_key_code == VKEY_F10;
-  if ((is_unmodified_menu_key &&
-       event.GetType() == kContextMenuKeyTriggeringEventType) ||
-      (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) {
-    View()->SendContextMenuEvent();
-    return WebInputEventResult::kHandledSystem;
-  }
-#endif  // !defined(OS_MAC)
-
-  return WebInputEventResult::kNotHandled;
-}
-
-void WebFrameWidgetBase::HandleMouseDown(LocalFrame& local_root,
-                                         const WebMouseEvent& event) {
-  WebViewImpl* view_impl = View();
-  // If there is a popup open, close it as the user is clicking on the page
-  // (outside of the popup). We also save it so we can prevent a click on an
-  // element from immediately reopening the same popup.
-  scoped_refptr<WebPagePopupImpl> page_popup;
-  if (event.button == WebMouseEvent::Button::kLeft) {
-    page_popup = view_impl->GetPagePopup();
-    view_impl->CancelPagePopup();
-  }
-
-  // Take capture on a mouse down on a plugin so we can send it mouse events.
-  // If the hit node is a plugin but a scrollbar is over it don't start mouse
-  // capture because it will interfere with the scrollbar receiving events.
-  PhysicalOffset point(LayoutUnit(event.PositionInWidget().x()),
-                       LayoutUnit(event.PositionInWidget().y()));
-  if (event.button == WebMouseEvent::Button::kLeft) {
-    HitTestLocation location(
-        LocalRootImpl()->GetFrameView()->ConvertFromRootFrame(point));
-    HitTestResult result(
-        LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
-            location));
-    result.SetToShadowHostIfInRestrictedShadowRoot();
-    Node* hit_node = result.InnerNode();
-    auto* html_element = DynamicTo<HTMLElement>(hit_node);
-    if (!result.GetScrollbar() && hit_node && hit_node->GetLayoutObject() &&
-        hit_node->GetLayoutObject()->IsEmbeddedObject() && html_element &&
-        html_element->IsPluginElement()) {
-      mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
-      SetMouseCapture(true);
-      TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
-                                        TRACE_ID_LOCAL(this));
-    }
-  }
-
-  PageWidgetEventHandler::HandleMouseDown(local_root, event);
-  // PageWidgetEventHandler may have detached the frame.
-  if (!LocalRootImpl())
-    return;
-
-  if (view_impl->GetPagePopup() && page_popup &&
-      view_impl->GetPagePopup()->HasSamePopupClient(page_popup.get())) {
-    // That click triggered a page popup that is the same as the one we just
-    // closed.  It needs to be closed.
-    view_impl->CancelPagePopup();
-  }
-
-  // Dispatch the contextmenu event regardless of if the click was swallowed.
-  if (!GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
-#if defined(OS_MAC)
-    if (event.button == WebMouseEvent::Button::kRight ||
-        (event.button == WebMouseEvent::Button::kLeft &&
-         event.GetModifiers() & WebMouseEvent::kControlKey))
-      MouseContextMenu(event);
-#else
-    if (event.button == WebMouseEvent::Button::kRight)
-      MouseContextMenu(event);
-#endif
-  }
-}
-
-void WebFrameWidgetBase::HandleMouseLeave(LocalFrame& local_root,
-                                          const WebMouseEvent& event) {
-  View()->SetMouseOverURL(WebURL());
-  PageWidgetEventHandler::HandleMouseLeave(local_root, event);
-  // PageWidgetEventHandler may have detached the frame.
-}
-
-void WebFrameWidgetBase::MouseContextMenu(const WebMouseEvent& event) {
-  GetPage()->GetContextMenuController().ClearContextMenu();
-
-  WebMouseEvent transformed_event =
-      TransformWebMouseEvent(LocalRootImpl()->GetFrameView(), event);
-  transformed_event.menu_source_type = kMenuSourceMouse;
-
-  // Find the right target frame. See issue 1186900.
-  HitTestResult result = HitTestResultForRootFramePos(
-      FloatPoint(transformed_event.PositionInRootFrame()));
-  Frame* target_frame;
-  if (result.InnerNodeOrImageMapImage())
-    target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
-  else
-    target_frame = GetPage()->GetFocusController().FocusedOrMainFrame();
-
-  // This will need to be changed to a nullptr check when focus control
-  // is refactored, at which point focusedOrMainFrame will never return a
-  // RemoteFrame.
-  // See https://crbug.com/341918.
-  LocalFrame* target_local_frame = DynamicTo<LocalFrame>(target_frame);
-  if (!target_local_frame)
-    return;
-
-  {
-    ContextMenuAllowedScope scope;
-    target_local_frame->GetEventHandler().SendContextMenuEvent(
-        transformed_event);
-  }
-  // Actually showing the context menu is handled by the ContextMenuClient
-  // implementation...
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleMouseUp(
-    LocalFrame& local_root,
-    const WebMouseEvent& event) {
-  WebInputEventResult result =
-      PageWidgetEventHandler::HandleMouseUp(local_root, event);
-  // PageWidgetEventHandler may have detached the frame.
-  if (!LocalRootImpl())
-    return result;
-
-  if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
-    // Dispatch the contextmenu event regardless of if the click was swallowed.
-    // On Mac/Linux, we handle it on mouse down, not up.
-    if (event.button == WebMouseEvent::Button::kRight)
-      MouseContextMenu(event);
-  }
-  return result;
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleGestureEvent(
-    const WebGestureEvent& event) {
-  WebInputEventResult event_result = WebInputEventResult::kNotHandled;
-
-  // Fling events are not sent to the renderer.
-  CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingStart);
-  CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingCancel);
-
-  WebViewImpl* web_view = View();
-
-  LocalFrame* frame = LocalRootImpl()->GetFrame();
-  WebGestureEvent scaled_event = TransformWebGestureEvent(frame->View(), event);
-
-  // Special handling for double tap and scroll events as we don't want to
-  // hit test for them.
-  switch (event.GetType()) {
-    case WebInputEvent::Type::kGestureDoubleTap:
-      if (web_view->SettingsImpl()->DoubleTapToZoomEnabled() &&
-          web_view->MinimumPageScaleFactor() !=
-              web_view->MaximumPageScaleFactor()) {
-        IntPoint pos_in_local_frame_root =
-            FlooredIntPoint(scaled_event.PositionInRootFrame());
-        auto block_bounds =
-            gfx::Rect(ComputeBlockBound(pos_in_local_frame_root, false));
-
-        if (ForMainFrame()) {
-          web_view->AnimateDoubleTapZoom(pos_in_local_frame_root,
-                                       WebRect(block_bounds));
-        } else {
-          // This sends the tap point and bounds to the main frame renderer via
-          // the browser, where their coordinates will be transformed into the
-          // main frame's coordinate space.
-          GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
-              pos_in_local_frame_root, block_bounds);
-        }
-      }
-      event_result = WebInputEventResult::kHandledSystem;
-      DidHandleGestureEvent(event);
-      return event_result;
-    case WebInputEvent::Type::kGestureScrollBegin:
-    case WebInputEvent::Type::kGestureScrollEnd:
-    case WebInputEvent::Type::kGestureScrollUpdate:
-      // If we are getting any scroll toss close any page popup that is open.
-      web_view->CancelPagePopup();
-
-      // Scrolling-related gesture events invoke EventHandler recursively for
-      // each frame down the chain, doing a single-frame hit-test per frame.
-      // This matches handleWheelEvent.  Perhaps we could simplify things by
-      // rewriting scroll handling to work inner frame out, and then unify with
-      // other gesture events.
-      event_result =
-          frame->GetEventHandler().HandleGestureScrollEvent(scaled_event);
-      DidHandleGestureEvent(event);
-      return event_result;
-    default:
-      break;
-  }
-
-  // Hit test across all frames and do touch adjustment as necessary for the
-  // event type.
-  GestureEventWithHitTestResults targeted_event =
-      frame->GetEventHandler().TargetGestureEvent(scaled_event);
-
-  // Link highlight animations are only for the main frame.
-  if (ForMainFrame()) {
-    // Handle link highlighting outside the main switch to avoid getting lost in
-    // the complicated set of cases handled below.
-    switch (scaled_event.GetType()) {
-      case WebInputEvent::Type::kGestureShowPress:
-        // Queue a highlight animation, then hand off to regular handler.
-        web_view->EnableTapHighlightAtPoint(targeted_event);
-        break;
-      case WebInputEvent::Type::kGestureTapCancel:
-      case WebInputEvent::Type::kGestureTap:
-      case WebInputEvent::Type::kGestureLongPress:
-        GetPage()->GetLinkHighlight().StartHighlightAnimationIfNeeded();
-        break;
-      default:
-        break;
-    }
-  }
-
-  switch (scaled_event.GetType()) {
-    case WebInputEvent::Type::kGestureTap: {
-      {
-        ContextMenuAllowedScope scope;
-        event_result =
-            frame->GetEventHandler().HandleGestureEvent(targeted_event);
-      }
-
-      if (web_view->GetPagePopup() && last_hidden_page_popup_ &&
-          web_view->GetPagePopup()->HasSamePopupClient(
-              last_hidden_page_popup_.get())) {
-        // The tap triggered a page popup that is the same as the one we just
-        // closed. It needs to be closed.
-        web_view->CancelPagePopup();
-      }
-      // Don't have this value persist outside of a single tap gesture, plus
-      // we're done with it now.
-      last_hidden_page_popup_ = nullptr;
-      break;
-    }
-    case WebInputEvent::Type::kGestureTwoFingerTap:
-    case WebInputEvent::Type::kGestureLongPress:
-    case WebInputEvent::Type::kGestureLongTap:
-      if (scaled_event.GetType() == WebInputEvent::Type::kGestureLongTap) {
-        if (LocalFrame* inner_frame =
-                targeted_event.GetHitTestResult().InnerNodeFrame()) {
-          if (!inner_frame->GetEventHandler().LongTapShouldInvokeContextMenu())
-            break;
-        } else if (!frame->GetEventHandler().LongTapShouldInvokeContextMenu()) {
-          break;
-        }
-      }
-
-      GetPage()->GetContextMenuController().ClearContextMenu();
-      {
-        ContextMenuAllowedScope scope;
-        event_result =
-            frame->GetEventHandler().HandleGestureEvent(targeted_event);
-      }
-
-      break;
-    case WebInputEvent::Type::kGestureTapDown:
-      // Touch pinch zoom and scroll on the page (outside of a popup) must hide
-      // the popup. In case of a touch scroll or pinch zoom, this function is
-      // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
-      // When we close a popup because of a GestureTapDown, we also save it so
-      // we can prevent the following GestureTap from immediately reopening the
-      // same popup.
-      // This value should not persist outside of a gesture, so is cleared by
-      // GestureTap (where it is used) and by GestureCancel.
-      last_hidden_page_popup_ = web_view->GetPagePopup();
-      web_view->CancelPagePopup();
-      event_result =
-          frame->GetEventHandler().HandleGestureEvent(targeted_event);
-      break;
-    case WebInputEvent::Type::kGestureTapCancel:
-      // Don't have this value persist outside of a single tap gesture.
-      last_hidden_page_popup_ = nullptr;
-      event_result =
-          frame->GetEventHandler().HandleGestureEvent(targeted_event);
-      break;
-    case WebInputEvent::Type::kGestureShowPress:
-    case WebInputEvent::Type::kGestureTapUnconfirmed:
-      event_result =
-          frame->GetEventHandler().HandleGestureEvent(targeted_event);
-      break;
-    default:
-      NOTREACHED();
-  }
-  DidHandleGestureEvent(event);
-  return event_result;
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleMouseWheel(
-    LocalFrame& frame,
-    const WebMouseWheelEvent& event) {
-  View()->CancelPagePopup();
-  return PageWidgetEventHandler::HandleMouseWheel(frame, event);
-  // PageWidgetEventHandler may have detached the frame.
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleCharEvent(
-    const WebKeyboardEvent& event) {
-  DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
-
-  // Please refer to the comments explaining the m_suppressNextKeypressEvent
-  // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
-  // handled by Webkit. A keyDown event is typically associated with a
-  // keyPress(char) event and a keyUp event. We reset this flag here as it
-  // only applies to the current keyPress event.
-  bool suppress = suppress_next_keypress_event_;
-  suppress_next_keypress_event_ = false;
-
-  // If there is a popup open, it should be the one processing the event,
-  // not the page.
-  scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
-  if (page_popup)
-    return page_popup->HandleKeyEvent(event);
-
-  LocalFrame* frame = To<LocalFrame>(FocusedCoreFrame());
-  if (!frame) {
-    return suppress ? WebInputEventResult::kHandledSuppressed
-                    : WebInputEventResult::kNotHandled;
-  }
-
-  EventHandler& handler = frame->GetEventHandler();
-
-  if (!event.IsCharacterKey())
-    return WebInputEventResult::kHandledSuppressed;
-
-  // Accesskeys are triggered by char events and can't be suppressed.
-  // It is unclear whether a keypress should be dispatched as well
-  // crbug.com/563507
-  if (handler.HandleAccessKey(event))
-    return WebInputEventResult::kHandledSystem;
-
-  // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
-  // the eventHandler::keyEvent. We mimic this behavior on all platforms since
-  // for now we are converting other platform's key events to windows key
-  // events.
-  if (event.is_system_key)
-    return WebInputEventResult::kNotHandled;
-
-  if (suppress)
-    return WebInputEventResult::kHandledSuppressed;
-
-  WebInputEventResult result = handler.KeyEvent(event);
-  if (result != WebInputEventResult::kNotHandled)
-    return result;
-
-  return WebInputEventResult::kNotHandled;
-}
-
-void WebFrameWidgetBase::CancelDrag() {
-  // It's possible for this to be called while we're not doing a drag if
-  // it's from a previous page that got unloaded.
-  if (!doing_drag_and_drop_)
-    return;
-  GetPage()->GetDragController().DragEnded();
-  doing_drag_and_drop_ = false;
-}
-
-void WebFrameWidgetBase::StartDragging(const WebDragData& drag_data,
-                                       DragOperationsMask operations_allowed,
-                                       const SkBitmap& drag_image,
-                                       const gfx::Point& drag_image_offset) {
-  doing_drag_and_drop_ = true;
-  if (Client()->InterceptStartDragging(drag_data, operations_allowed,
-                                       drag_image, drag_image_offset)) {
-    return;
-  }
-
-  gfx::Point offset_in_dips =
-      widget_base_->BlinkSpaceToFlooredDIPs(drag_image_offset);
-  GetAssociatedFrameWidgetHost()->StartDragging(
-      drag_data, operations_allowed, drag_image,
-      gfx::Vector2d(offset_in_dips.x(), offset_in_dips.y()),
-      possible_drag_event_info_.Clone());
-}
-
-DragOperation WebFrameWidgetBase::DragTargetDragEnterOrOver(
-    const gfx::PointF& point_in_viewport,
-    const gfx::PointF& screen_point,
-    DragAction drag_action,
-    uint32_t key_modifiers) {
-  DCHECK(current_drag_data_);
-  // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be
-  // null here, but this is somehow happening (rarely). This suggests that in
-  // some cases drag-over is happening before drag-enter, which should be
-  // impossible. This needs to be investigated further. Once fixed, the extra
-  // check for |!m_currentDragData| should be removed. (crbug.com/671504)
-  if (IgnoreInputEvents() || !current_drag_data_) {
-    CancelDrag();
-    return kDragOperationNone;
-  }
-
-  FloatPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport));
-
-  current_drag_data_->SetModifiers(key_modifiers);
-  DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
-                     FloatPoint(screen_point), operations_allowed_);
-
-  DragOperation drag_operation =
-      GetPage()->GetDragController().DragEnteredOrUpdated(
-          &drag_data, *local_root_->GetFrame());
-
-  // Mask the drag operation against the drag source's allowed
-  // operations.
-  if (!(drag_operation & drag_data.DraggingSourceOperationMask()))
-    drag_operation = kDragOperationNone;
-
-  drag_operation_ = drag_operation;
-
-  return drag_operation_;
-}
-
-void WebFrameWidgetBase::SendOverscrollEventFromImplSide(
-    const gfx::Vector2dF& overscroll_delta,
-    cc::ElementId scroll_latched_element_id) {
-  if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
-    return;
-
-  Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
-      scroll_latched_element_id);
-  if (target_node) {
-    target_node->GetDocument().EnqueueOverscrollEventForNode(
-        target_node, overscroll_delta.x(), overscroll_delta.y());
-  }
-}
-
-void WebFrameWidgetBase::SendScrollEndEventFromImplSide(
-    cc::ElementId scroll_latched_element_id) {
-  if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
-    return;
-
-  Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
-      scroll_latched_element_id);
-  if (target_node)
-    target_node->GetDocument().EnqueueScrollEndEventForNode(target_node);
-}
-
-WebInputMethodController*
-WebFrameWidgetBase::GetActiveWebInputMethodController() const {
-  WebLocalFrameImpl* local_frame =
-      WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
-  return local_frame ? local_frame->GetInputMethodController() : nullptr;
-}
-
-gfx::PointF WebFrameWidgetBase::ViewportToRootFrame(
-    const gfx::PointF& point_in_viewport) const {
-  return GetPage()->GetVisualViewport().ViewportToRootFrame(
-      FloatPoint(point_in_viewport));
-}
-
-WebViewImpl* WebFrameWidgetBase::View() const {
-  return local_root_->ViewImpl();
-}
-
-Page* WebFrameWidgetBase::GetPage() const {
-  return View()->GetPage();
-}
-
-mojom::blink::FrameWidgetHost*
-WebFrameWidgetBase::GetAssociatedFrameWidgetHost() const {
-  return frame_widget_host_.get();
-}
-
-void WebFrameWidgetBase::RequestDecode(
-    const PaintImage& image,
-    base::OnceCallback<void(bool)> callback) {
-  widget_base_->LayerTreeHost()->QueueImageDecode(image, std::move(callback));
-
-  // In web tests the request does not actually cause a commit, because the
-  // compositor is scheduled by the test runner to avoid flakiness. So for this
-  // case we must request a main frame.
-  Client()->ScheduleAnimationForWebTests();
-}
-
-void WebFrameWidgetBase::Trace(Visitor* visitor) const {
-  visitor->Trace(local_root_);
-  visitor->Trace(current_drag_data_);
-  visitor->Trace(frame_widget_host_);
-  visitor->Trace(receiver_);
-  visitor->Trace(input_target_receiver_);
-  visitor->Trace(mouse_capture_element_);
-  visitor->Trace(device_emulator_);
-}
-
-void WebFrameWidgetBase::SetNeedsRecalculateRasterScales() {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->SetNeedsRecalculateRasterScales();
-}
-
-void WebFrameWidgetBase::SetBackgroundColor(SkColor color) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->set_background_color(color);
-}
-
-void WebFrameWidgetBase::SetOverscrollBehavior(
-    const cc::OverscrollBehavior& overscroll_behavior) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->SetOverscrollBehavior(overscroll_behavior);
-}
-
-void WebFrameWidgetBase::RegisterSelection(cc::LayerSelection selection) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->RegisterSelection(selection);
-}
-
-void WebFrameWidgetBase::StartPageScaleAnimation(
-    const gfx::Vector2d& destination,
-    bool use_anchor,
-    float new_page_scale,
-    base::TimeDelta duration) {
-  widget_base_->LayerTreeHost()->StartPageScaleAnimation(
-      destination, use_anchor, new_page_scale, duration);
-}
-
-void WebFrameWidgetBase::RequestBeginMainFrameNotExpected(bool request) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->RequestBeginMainFrameNotExpected(request);
-}
-
-void WebFrameWidgetBase::DidCommitAndDrawCompositorFrame() {
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrame* local_frame) {
-        local_frame->Client()->DidCommitAndDrawCompositorFrame();
-      }));
-}
-
-void WebFrameWidgetBase::DidObserveFirstScrollDelay(
-    base::TimeDelta first_scroll_delay,
-    base::TimeTicks first_scroll_timestamp) {
-  if (!local_root_ || !(local_root_->GetFrame()) ||
-      !(local_root_->GetFrame()->GetDocument())) {
-    return;
-  }
-  InteractiveDetector* interactive_detector =
-      InteractiveDetector::From(*(local_root_->GetFrame()->GetDocument()));
-  if (interactive_detector) {
-    interactive_detector->DidObserveFirstScrollDelay(first_scroll_delay,
-                                                     first_scroll_timestamp);
-  }
-}
-
-std::unique_ptr<cc::LayerTreeFrameSink>
-WebFrameWidgetBase::AllocateNewLayerTreeFrameSink() {
-  return Client()->AllocateNewLayerTreeFrameSink();
-}
-
-void WebFrameWidgetBase::DidBeginMainFrame() {
-  Client()->DidBeginMainFrame();
-  DCHECK(LocalRootImpl()->GetFrame());
-  PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame());
-}
-
-void WebFrameWidgetBase::UpdateLifecycle(WebLifecycleUpdate requested_update,
-                                         DocumentUpdateReason reason) {
-  TRACE_EVENT0("blink", "WebFrameWidgetBase::UpdateLifecycle");
-  if (!LocalRootImpl())
-    return;
-
-  PageWidgetDelegate::UpdateLifecycle(*GetPage(), *LocalRootImpl()->GetFrame(),
-                                      requested_update, reason);
-  if (requested_update != WebLifecycleUpdate::kAll)
-    return;
-
-  View()->UpdatePagePopup();
-
-  // Meaningful layout events and background colors only apply to main frames.
-  if (ForMainFrame()) {
-    MainFrameData& data = main_data();
-
-    // There is no background color for non-composited WebViews (eg
-    // printing).
-    if (View()->does_composite()) {
-      SkColor background_color = View()->BackgroundColor();
-      SetBackgroundColor(background_color);
-      if (background_color != data.last_background_color) {
-        LocalRootImpl()->GetFrame()->DidChangeBackgroundColor(
-            background_color, false /* color_adjust */);
-        data.last_background_color = background_color;
-      }
-    }
-
-    if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
-      LocalFrame* frame = LocalRootImpl()->GetFrame();
-
-      if (data.should_dispatch_first_visually_non_empty_layout &&
-          view->IsVisuallyNonEmpty()) {
-        data.should_dispatch_first_visually_non_empty_layout = false;
-        // TODO(esprehn): Move users of this callback to something
-        // better, the heuristic for "visually non-empty" is bad.
-        DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
-      }
-
-      if (data.should_dispatch_first_layout_after_finished_parsing &&
-          frame->GetDocument()->HasFinishedParsing()) {
-        data.should_dispatch_first_layout_after_finished_parsing = false;
-        DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
-      }
-
-      if (data.should_dispatch_first_layout_after_finished_loading &&
-          frame->GetDocument()->IsLoadCompleted()) {
-        data.should_dispatch_first_layout_after_finished_loading = false;
-        DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
-      }
-    }
-  }
-}
-
-void WebFrameWidgetBase::WillBeginMainFrame() {
-  Client()->WillBeginMainFrame();
-}
-
-void WebFrameWidgetBase::DidCompletePageScaleAnimation() {
-  // Page scale animations only happen on the main frame.
-  DCHECK(ForMainFrame());
-  if (auto* focused_frame = View()->FocusedFrame()) {
-    if (focused_frame->AutofillClient())
-      focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
-  }
-}
-
-void WebFrameWidgetBase::ScheduleAnimation() {
-  Client()->ScheduleAnimation();
-}
-
-void WebFrameWidgetBase::FocusChanged(bool enable) {
-  // TODO(crbug.com/689777): FocusChange events are only sent to the MainFrame
-  // these maybe should goto the local root so that the rest of input messages
-  // sent to those are preserved in order.
-  DCHECK(ForMainFrame());
-  View()->SetPageFocus(enable);
-}
-
-bool WebFrameWidgetBase::ShouldAckSyntheticInputImmediately() {
-  // TODO(bokan): The RequestPresentation API appears not to function in VR. As
-  // a short term workaround for https://crbug.com/940063, ACK input
-  // immediately rather than using RequestPresentation.
-  if (GetPage()->GetSettings().GetImmersiveModeEnabled())
-    return true;
-  return false;
-}
-
-void WebFrameWidgetBase::UpdateVisualProperties(
-    const VisualProperties& visual_properties) {
-  SetZoomLevel(visual_properties.zoom_level);
-
-  // TODO(danakj): In order to synchronize updates between local roots, the
-  // display mode should be propagated to RenderFrameProxies and down through
-  // their RenderWidgetHosts to child WebFrameWidgetBase via the
-  // VisualProperties waterfall, instead of coming to each WebFrameWidgetBase
-  // independently.
-  // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode
-  SetDisplayMode(visual_properties.display_mode);
-
-  if (ForMainFrame()) {
-    SetAutoResizeMode(visual_properties.auto_resize_enabled,
-                      visual_properties.min_size_for_auto_resize,
-                      visual_properties.max_size_for_auto_resize,
-                      visual_properties.screen_info.device_scale_factor);
-  }
-
-  bool capture_sequence_number_changed =
-      visual_properties.capture_sequence_number !=
-      last_capture_sequence_number_;
-  if (capture_sequence_number_changed) {
-    last_capture_sequence_number_ = visual_properties.capture_sequence_number;
-
-    // Send the capture sequence number to RemoteFrames that are below the
-    // local root for this widget.
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](uint32_t capture_sequence_number, RemoteFrame* remote_frame) {
-          remote_frame->Client()->UpdateCaptureSequenceNumber(
-              capture_sequence_number);
-        },
-        visual_properties.capture_sequence_number));
-  }
-
-  if (!View()->AutoResizeMode()) {
-    if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_) {
-      is_fullscreen_granted_ = visual_properties.is_fullscreen_granted;
-      if (is_fullscreen_granted_)
-        View()->DidEnterFullscreen();
-      else
-        View()->DidExitFullscreen();
-    }
-  }
-
-  gfx::Size old_visible_viewport_size_in_dips =
-      widget_base_->VisibleViewportSizeInDIPs();
-  ApplyVisualPropertiesSizing(visual_properties);
-
-  if (old_visible_viewport_size_in_dips !=
-      widget_base_->VisibleViewportSizeInDIPs()) {
-    ForEachLocalFrameControlledByWidget(
-        local_root_->GetFrame(),
-        WTF::BindRepeating([](WebLocalFrame* local_frame) {
-          local_frame->Client()->ResetHasScrolledFocusedEditableIntoView();
-        }));
-
-    // Propagate changes down to child local root RenderWidgets and
-    // BrowserPlugins in other frame trees/processes.
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const gfx::Size& visible_viewport_size, RemoteFrame* remote_frame) {
-          remote_frame->Client()->DidChangeVisibleViewportSize(
-              visible_viewport_size);
-        },
-        widget_base_->VisibleViewportSizeInDIPs()));
-  }
-
-  // All non-top-level Widgets (child local-root frames, Portals, GuestViews,
-  // etc.) propagate and consume the page scale factor as "external", meaning
-  // that it comes from the top level widget's page scale.
-  if (!ForTopMostMainFrame()) {
-    // The main frame controls the page scale factor, from blink. For other
-    // frame widgets, the page scale is received from its parent as part of
-    // the visual properties here. While blink doesn't need to know this
-    // page scale factor outside the main frame, the compositor does in
-    // order to produce its output at the correct scale.
-    widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
-        visual_properties.page_scale_factor,
-        visual_properties.is_pinch_gesture_active);
-
-    NotifyPageScaleFactorChanged(visual_properties.page_scale_factor,
-                                 visual_properties.is_pinch_gesture_active);
-  } else {
-    // Ensure the external scale factor in top-level widgets is reset as it may
-    // be leftover from when a widget was nested and was promoted to top level
-    // (e.g. portal activation).
-    widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
-        1.f,
-        /*is_pinch_gesture_active=*/false);
-  }
-
-  // TODO(crbug.com/939118): ScrollFocusedNodeIntoViewForWidget does not work
-  // when the focused node is inside an OOPIF. This code path where
-  // scroll_focused_node_into_view is set is used only for WebView, crbug
-  // 939118 tracks fixing webviews to not use scroll_focused_node_into_view.
-  if (visual_properties.scroll_focused_node_into_view)
-    ScrollFocusedEditableElementIntoView();
-}
-
-void WebFrameWidgetBase::ApplyVisualPropertiesSizing(
-    const VisualProperties& visual_properties) {
-  gfx::Rect new_compositor_viewport_pixel_rect =
-      visual_properties.compositor_viewport_pixel_rect;
-  if (ForMainFrame()) {
-    if (size_ !=
-        widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size)) {
-      // Only hide popups when the size changes. Eg https://crbug.com/761908.
-      View()->CancelPagePopup();
-    }
-
-    if (auto* device_emulator = DeviceEmulator()) {
-      device_emulator->UpdateVisualProperties(visual_properties);
-      return;
-    }
-
-    if (AutoResizeMode()) {
-      new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize(
-          widget_base_->BlinkSpaceToFlooredDIPs(size_.value_or(gfx::Size())),
-          visual_properties.screen_info.device_scale_factor));
-    }
-  }
-
-  SetWindowSegments(visual_properties.root_widget_window_segments);
-
-  widget_base_->UpdateSurfaceAndScreenInfo(
-      visual_properties.local_surface_id.value_or(viz::LocalSurfaceId()),
-      new_compositor_viewport_pixel_rect, visual_properties.screen_info);
-
-  // Store this even when auto-resizing, it is the size of the full viewport
-  // used for clipping, and this value is propagated down the Widget
-  // hierarchy via the VisualProperties waterfall.
-  widget_base_->SetVisibleViewportSizeInDIPs(
-      visual_properties.visible_viewport_size);
-
-  if (ForMainFrame()) {
-    if (!AutoResizeMode()) {
-      size_ = widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size);
-
-      View()->ResizeWithBrowserControls(
-          size_.value(),
-          widget_base_->DIPsToCeiledBlinkSpace(
-              widget_base_->VisibleViewportSizeInDIPs()),
-          visual_properties.browser_controls_params);
-    }
-  } else {
-    // Widgets in a WebView's frame tree without a local main frame
-    // set the size of the WebView to be the |visible_viewport_size|, in order
-    // to limit compositing in (out of process) child frames to what is visible.
-    //
-    // Note that child frames in the same process/WebView frame tree as the
-    // main frame do not do this in order to not clobber the source of truth in
-    // the main frame.
-    if (!View()->MainFrameImpl()) {
-      View()->Resize(widget_base_->DIPsToCeiledBlinkSpace(
-          widget_base_->VisibleViewportSizeInDIPs()));
-    }
-
-    Resize(widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size));
-  }
-}
-
-void WebFrameWidgetBase::ScheduleAnimationForWebTests() {
-  Client()->ScheduleAnimationForWebTests();
-}
-
-int WebFrameWidgetBase::GetLayerTreeId() {
-  if (!View()->does_composite())
-    return 0;
-  return widget_base_->LayerTreeHost()->GetId();
-}
-
-void WebFrameWidgetBase::SetHaveScrollEventHandlers(bool has_handlers) {
-  widget_base_->LayerTreeHost()->SetHaveScrollEventHandlers(has_handlers);
-}
-
-void WebFrameWidgetBase::SetEventListenerProperties(
-    cc::EventListenerClass listener_class,
-    cc::EventListenerProperties listener_properties) {
-  widget_base_->LayerTreeHost()->SetEventListenerProperties(
-      listener_class, listener_properties);
-
-  if (listener_class == cc::EventListenerClass::kTouchStartOrMove ||
-      listener_class == cc::EventListenerClass::kTouchEndOrCancel) {
-    bool has_touch_handlers =
-        EventListenerProperties(cc::EventListenerClass::kTouchStartOrMove) !=
-            cc::EventListenerProperties::kNone ||
-        EventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel) !=
-            cc::EventListenerProperties::kNone;
-    if (!has_touch_handlers_ || *has_touch_handlers_ != has_touch_handlers) {
-      has_touch_handlers_ = has_touch_handlers;
-
-      // Can be NULL when running tests.
-      if (auto* scheduler_state = widget_base_->RendererWidgetSchedulingState())
-        scheduler_state->SetHasTouchHandler(has_touch_handlers);
-      // Set touch event consumers based on whether there are touch event
-      // handlers or the page has hit testable scrollbars.
-      auto touch_event_consumers = mojom::blink::TouchEventConsumers::New(
-          has_touch_handlers, GetPage()->GetScrollbarTheme().AllowsHitTest());
-      frame_widget_host_->SetHasTouchEventConsumers(
-          std::move(touch_event_consumers));
-    }
-  } else if (listener_class == cc::EventListenerClass::kPointerRawUpdate) {
-    SetHasPointerRawUpdateEventHandlers(listener_properties !=
-                                        cc::EventListenerProperties::kNone);
-  }
-}
-
-cc::EventListenerProperties WebFrameWidgetBase::EventListenerProperties(
-    cc::EventListenerClass listener_class) const {
-  return widget_base_->LayerTreeHost()->event_listener_properties(
-      listener_class);
-}
-
-mojom::blink::DisplayMode WebFrameWidgetBase::DisplayMode() const {
-  return display_mode_;
-}
-
-const WebVector<gfx::Rect>& WebFrameWidgetBase::WindowSegments() const {
-  return window_segments_;
-}
-
-void WebFrameWidgetBase::StartDeferringCommits(base::TimeDelta timeout) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->StartDeferringCommits(timeout);
-}
-
-void WebFrameWidgetBase::StopDeferringCommits(
-    cc::PaintHoldingCommitTrigger triggger) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->StopDeferringCommits(triggger);
-}
-
-std::unique_ptr<cc::ScopedDeferMainFrameUpdate>
-WebFrameWidgetBase::DeferMainFrameUpdate() {
-  return widget_base_->LayerTreeHost()->DeferMainFrameUpdate();
-}
-
-void WebFrameWidgetBase::SetBrowserControlsShownRatio(float top_ratio,
-                                                      float bottom_ratio) {
-  widget_base_->LayerTreeHost()->SetBrowserControlsShownRatio(top_ratio,
-                                                              bottom_ratio);
-}
-
-void WebFrameWidgetBase::SetBrowserControlsParams(
-    cc::BrowserControlsParams params) {
-  widget_base_->LayerTreeHost()->SetBrowserControlsParams(params);
-}
-
-cc::LayerTreeDebugState WebFrameWidgetBase::GetLayerTreeDebugState() {
-  return widget_base_->LayerTreeHost()->GetDebugState();
-}
-
-void WebFrameWidgetBase::SetLayerTreeDebugState(
-    const cc::LayerTreeDebugState& state) {
-  widget_base_->LayerTreeHost()->SetDebugState(state);
-}
-
-void WebFrameWidgetBase::SynchronouslyCompositeForTesting(
-    base::TimeTicks frame_time) {
-  widget_base_->LayerTreeHost()->CompositeForTest(frame_time, false);
-}
-
-void WebFrameWidgetBase::UseSynchronousResizeModeForTesting(bool enable) {
-  main_data().synchronous_resize_mode_for_testing = enable;
-}
-
-void WebFrameWidgetBase::SetDeviceColorSpaceForTesting(
-    const gfx::ColorSpace& color_space) {
-  DCHECK(ForMainFrame());
-  // We are changing the device color space from the renderer, so allocate a
-  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
-
-  blink::ScreenInfo info = widget_base_->GetScreenInfo();
-  info.display_color_spaces = gfx::DisplayColorSpaces(color_space);
-  widget_base_->UpdateScreenInfo(info);
-}
-
-// TODO(665924): Remove direct dispatches of mouse events from
-// PointerLockController, instead passing them through EventHandler.
-void WebFrameWidgetBase::PointerLockMouseEvent(
-    const WebCoalescedInputEvent& coalesced_event) {
-  const WebInputEvent& input_event = coalesced_event.Event();
-  const WebMouseEvent& mouse_event =
-      static_cast<const WebMouseEvent&>(input_event);
-  WebMouseEvent transformed_event =
-      TransformWebMouseEvent(local_root_->GetFrameView(), mouse_event);
-
-  AtomicString event_type;
-  switch (input_event.GetType()) {
-    case WebInputEvent::Type::kMouseDown:
-      event_type = event_type_names::kMousedown;
-      if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
-        break;
-      LocalFrame::NotifyUserActivation(
-          GetPage()
-              ->GetPointerLockController()
-              .GetElement()
-              ->GetDocument()
-              .GetFrame(),
-          mojom::blink::UserActivationNotificationType::kInteraction);
-      break;
-    case WebInputEvent::Type::kMouseUp:
-      event_type = event_type_names::kMouseup;
-      break;
-    case WebInputEvent::Type::kMouseMove:
-      event_type = event_type_names::kMousemove;
-      break;
-    default:
-      NOTREACHED() << input_event.GetType();
-  }
-
-  if (GetPage()) {
-    GetPage()->GetPointerLockController().DispatchLockedMouseEvent(
-        transformed_event,
-        TransformWebMouseEventVector(
-            local_root_->GetFrameView(),
-            coalesced_event.GetCoalescedEventsPointers()),
-        TransformWebMouseEventVector(
-            local_root_->GetFrameView(),
-            coalesced_event.GetPredictedEventsPointers()),
-        event_type);
-  }
-}
-bool WebFrameWidgetBase::IsPointerLocked() {
-  if (GetPage()) {
-    return GetPage()->GetPointerLockController().IsPointerLocked();
-  }
-  return false;
-}
-
-void WebFrameWidgetBase::ShowContextMenu(
-    ui::mojom::blink::MenuSourceType source_type,
-    const gfx::Point& location) {
-  host_context_menu_location_ = location;
-
-  if (!GetPage())
-    return;
-  GetPage()->GetContextMenuController().ClearContextMenu();
-  {
-    ContextMenuAllowedScope scope;
-    if (LocalFrame* focused_frame =
-            GetPage()->GetFocusController().FocusedFrame()) {
-      focused_frame->GetEventHandler().ShowNonLocatedContextMenu(
-          nullptr, static_cast<blink::WebMenuSourceType>(source_type));
-    }
-  }
-  host_context_menu_location_.reset();
-}
-
-void WebFrameWidgetBase::SetViewportIntersection(
-    mojom::blink::ViewportIntersectionStatePtr intersection_state) {
-  // Remote viewports are only applicable to local frames with remote ancestors.
-  // TODO(https://crbug.com/1148960): Should this deal with portals?
-  DCHECK(ForSubframe());
-
-  child_data().compositor_visible_rect =
-      intersection_state->compositor_visible_rect;
-  widget_base_->LayerTreeHost()->SetViewportVisibleRect(
-      intersection_state->compositor_visible_rect);
-  LocalRootImpl()->GetFrame()->SetViewportIntersectionFromParent(
-      *intersection_state);
-}
-
-void WebFrameWidgetBase::EnableDeviceEmulation(
-    const DeviceEmulationParams& parameters) {
-  // Device Emaulation is only supported for the main frame.
-  DCHECK(ForMainFrame());
-  if (!device_emulator_) {
-    gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
-
-    device_emulator_ = MakeGarbageCollected<ScreenMetricsEmulator>(
-        this, widget_base_->GetScreenInfo(), size_in_dips,
-        widget_base_->VisibleViewportSizeInDIPs(),
-        widget_base_->WidgetScreenRect(), widget_base_->WindowScreenRect());
-  }
-  device_emulator_->ChangeEmulationParams(parameters);
-}
-
-void WebFrameWidgetBase::DisableDeviceEmulation() {
-  if (!device_emulator_)
-    return;
-  device_emulator_->DisableAndApply();
-  device_emulator_ = nullptr;
-}
-
-void WebFrameWidgetBase::SetIsInertForSubFrame(bool inert) {
-  DCHECK(ForSubframe());
-  LocalRootImpl()->GetFrame()->SetIsInert(inert);
-}
-
-base::Optional<gfx::Point>
-WebFrameWidgetBase::GetAndResetContextMenuLocation() {
-  return std::move(host_context_menu_location_);
-}
-
-void WebFrameWidgetBase::SetZoomLevel(double zoom_level) {
-  // Override the zoom level with the testing one if necessary.
-  if (zoom_level_for_testing_ != -INFINITY)
-    zoom_level = zoom_level_for_testing_;
-
-  View()->SetZoomLevel(zoom_level);
-
-  // Part of the UpdateVisualProperties dance we send the zoom level to
-  // RemoteFrames that are below the local root for this widget.
-  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-      [](double zoom_level, RemoteFrame* remote_frame) {
-        remote_frame->Client()->ZoomLevelChanged(zoom_level);
-      },
-      zoom_level));
-}
-
-void WebFrameWidgetBase::SetAutoResizeMode(bool auto_resize,
-                                           const gfx::Size& min_window_size,
-                                           const gfx::Size& max_window_size,
-                                           float device_scale_factor) {
-  // Auto resize only applies to main frames.
-  DCHECK(ForMainFrame());
-
-  if (auto_resize) {
-    if (!Platform::Current()->IsUseZoomForDSFEnabled())
-      device_scale_factor = 1.f;
-    View()->EnableAutoResizeMode(
-        gfx::ScaleToCeiledSize(min_window_size, device_scale_factor),
-        gfx::ScaleToCeiledSize(max_window_size, device_scale_factor));
-  } else if (AutoResizeMode()) {
-    View()->DisableAutoResizeMode();
-  }
-}
-
-void WebFrameWidgetBase::DidAutoResize(const gfx::Size& size) {
-  DCHECK(ForMainFrame());
-  gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(size);
-  size_ = size;
-
-  if (main_data().synchronous_resize_mode_for_testing) {
-    gfx::Rect new_pos(widget_base_->WindowRect());
-    new_pos.set_size(size_in_dips);
-    SetScreenRects(new_pos, new_pos);
-  }
-
-  // TODO(ccameron): Note that this destroys any information differentiating
-  // |size| from the compositor's viewport size.
-  gfx::Rect size_with_dsf = gfx::Rect(gfx::ScaleToCeiledSize(
-      gfx::Rect(size_in_dips).size(),
-      widget_base_->GetScreenInfo().device_scale_factor));
-  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
-  widget_base_->UpdateCompositorViewportRect(size_with_dsf);
-}
-
-LocalFrame* WebFrameWidgetBase::FocusedLocalFrameInWidget() const {
-  if (!local_root_) {
-    // WebFrameWidget is created in the call to CreateFrame. The corresponding
-    // RenderWidget, however, might not swap in right away (InstallNewDocument()
-    // will lead to it swapping in). During this interval local_root_ is nullptr
-    // (see https://crbug.com/792345).
-    return nullptr;
-  }
-
-  LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
-  return (frame && frame->LocalFrameRoot() == local_root_->GetFrame())
-             ? frame
-             : nullptr;
-}
-
-WebLocalFrame* WebFrameWidgetBase::FocusedWebLocalFrameInWidget() const {
-  return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
-}
-
-bool WebFrameWidgetBase::ScrollFocusedEditableElementIntoView() {
-  Element* element = FocusedElement();
-  if (!element || !WebElement(element).IsEditable())
-    return false;
-
-  element->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
-
-  if (!element->GetLayoutObject())
-    return false;
-
-  PhysicalRect rect_to_scroll;
-  auto params =
-      GetScrollParamsForFocusedEditableElement(*element, rect_to_scroll);
-  element->GetLayoutObject()->ScrollRectToVisible(rect_to_scroll,
-                                                  std::move(params));
-
-  // Second phase for main frames is to schedule a zoom animation.
-  if (ForMainFrame()) {
-    LocalFrameView* main_frame_view = LocalRootImpl()->GetFrame()->View();
-
-    View()->ZoomAndScrollToFocusedEditableElementRect(
-        main_frame_view->RootFrameToDocument(
-            element->GetDocument().View()->ConvertToRootFrame(
-                element->GetLayoutObject()->AbsoluteBoundingBoxRect())),
-        main_frame_view->RootFrameToDocument(
-            element->GetDocument().View()->ConvertToRootFrame(
-                element->GetDocument()
-                    .GetFrame()
-                    ->Selection()
-                    .ComputeRectToScroll(kDoNotRevealExtent))),
-        View()->ShouldZoomToLegibleScale(*element));
-  }
-
-  return true;
-}
-
-void WebFrameWidgetBase::ResetMeaningfulLayoutStateForMainFrame() {
-  MainFrameData& data = main_data();
-  data.should_dispatch_first_visually_non_empty_layout = true;
-  data.should_dispatch_first_layout_after_finished_parsing = true;
-  data.should_dispatch_first_layout_after_finished_loading = true;
-}
-
-cc::LayerTreeHost* WebFrameWidgetBase::InitializeCompositing(
-    scheduler::WebThreadScheduler* main_thread_scheduler,
-    cc::TaskGraphRunner* task_graph_runner,
-    const ScreenInfo& screen_info,
-    std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
-    const cc::LayerTreeSettings* settings) {
-  widget_base_->InitializeCompositing(
-      main_thread_scheduler, task_graph_runner, is_for_child_local_root_,
-      screen_info, std::move(ukm_recorder_factory), settings);
-
-  LocalFrameView* frame_view;
-  if (is_for_child_local_root_) {
-    frame_view = LocalRootImpl()->GetFrame()->View();
-  } else {
-    // Scrolling for the root frame is special we need to pass null indicating
-    // we are at the top of the tree when setting up the Animation. Which will
-    // cause ownership of the timeline and animation host.
-    // See ScrollingCoordinator::AnimationHostInitialized.
-    frame_view = nullptr;
-  }
-
-  GetPage()->AnimationHostInitialized(*AnimationHost(), frame_view);
-  return widget_base_->LayerTreeHost();
-}
-
-void WebFrameWidgetBase::SetCompositorVisible(bool visible) {
-  widget_base_->SetCompositorVisible(visible);
-}
-
-gfx::Size WebFrameWidgetBase::Size() {
-  return size_.value_or(gfx::Size());
-}
-
-void WebFrameWidgetBase::Resize(const gfx::Size& new_size) {
-  if (size_ && *size_ == new_size)
-    return;
-
-  if (ForMainFrame()) {
-    size_ = new_size;
-    View()->Resize(new_size);
-    return;
-  }
-
-  if (child_data().did_suspend_parsing) {
-    child_data().did_suspend_parsing = false;
-    LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->ResumeParser();
-  }
-
-  LocalFrameView* view = LocalRootImpl()->GetFrameView();
-  DCHECK(view);
-
-  size_ = new_size;
-
-  view->SetLayoutSize(IntSize(*size_));
-  view->Resize(IntSize(*size_));
-
-  // FIXME: In WebViewImpl this layout was a precursor to setting the minimum
-  // scale limit.  It is not clear if this is necessary for frame-level widget
-  // resize.
-  if (view->NeedsLayout())
-    view->UpdateLayout();
-
-  // FIXME: Investigate whether this is needed; comment from eseidel suggests
-  // that this function is flawed.
-  // TODO(kenrb): It would probably make more sense to check whether lifecycle
-  // updates are throttled in the root's LocalFrameView, but for OOPIFs that
-  // doesn't happen. Need to investigate if OOPIFs can be throttled during
-  // load.
-  if (LocalRootImpl()->GetFrame()->GetDocument()->IsLoadCompleted()) {
-    // FIXME: This is wrong. The LocalFrameView is responsible sending a
-    // resizeEvent as part of layout. Layout is also responsible for sending
-    // invalidations to the embedder. This method and all callers may be wrong.
-    // -- eseidel.
-    LocalRootImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent();
-
-    // Pass the limits even though this is for subframes, as the limits will
-    // be needed in setting the raster scale. We set this value when setting
-    // up the compositor, but need to update it when the limits of the
-    // WebViewImpl have changed.
-    // TODO(wjmaclean): This is updating when the size of the *child frame*
-    // have changed which are completely independent of the WebView, and in an
-    // OOPIF where the main frame is remote, are these limits even useful?
-    SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
-                               View()->MinimumPageScaleFactor(),
-                               View()->MaximumPageScaleFactor());
-  }
-}
-
-void WebFrameWidgetBase::BeginMainFrame(base::TimeTicks last_frame_time) {
-  TRACE_EVENT1("blink", "WebFrameWidgetBase::BeginMainFrame", "frameTime",
-               last_frame_time);
-  DCHECK(!last_frame_time.is_null());
-  CHECK(LocalRootImpl());
-
-  // Dirty bit on MouseEventManager is not cleared in OOPIFs after scroll
-  // or layout changes. Ensure the hover state is recomputed if necessary.
-  LocalRootImpl()
-      ->GetFrame()
-      ->GetEventHandler()
-      .RecomputeMouseHoverStateIfNeeded();
-
-  // Adjusting frame anchor only happens on the main frame.
-  if (ForMainFrame()) {
-    if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
-      if (FragmentAnchor* anchor = view->GetFragmentAnchor())
-        anchor->PerformPreRafActions();
-    }
-  }
-
-  base::Optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer;
-  if (WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
-    ukm_timer.emplace(LocalRootImpl()
-                          ->GetFrame()
-                          ->View()
-                          ->EnsureUkmAggregator()
-                          .GetScopedTimer(LocalFrameUkmAggregator::kAnimate));
-  }
-
-  PageWidgetDelegate::Animate(*GetPage(), last_frame_time);
-  // Animate can cause the local frame to detach.
-  if (!LocalRootImpl())
-    return;
-
-  GetPage()->GetValidationMessageClient().LayoutOverlay();
-}
-
-void WebFrameWidgetBase::BeginCommitCompositorFrame() {
-  commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
-}
-
-void WebFrameWidgetBase::EndCommitCompositorFrame(
-    base::TimeTicks commit_start_time) {
-  DCHECK(commit_compositor_frame_start_time_.has_value());
-  if (ForMainFrame()) {
-    View()->Client()->DidCommitCompositorFrameForLocalMainFrame(
-        commit_start_time);
-    View()->UpdatePreferredSize();
-    if (!View()->MainFrameImpl()) {
-      // Trying to track down why the view's idea of the main frame varies
-      // from LocalRootImpl's.
-      // TODO(https://crbug.com/1139104): Remove this.
-      std::string reason = View()->GetNullFrameReasonForBug1139104();
-      DCHECK(false) << reason;
-      SCOPED_CRASH_KEY_STRING32(Crbug1139104, NullFrameReason, reason);
-      base::debug::DumpWithoutCrashing();
-    }
-  }
-
-  LocalRootImpl()
-      ->GetFrame()
-      ->View()
-      ->EnsureUkmAggregator()
-      .RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
-                                  commit_start_time, base::TimeTicks::Now());
-  commit_compositor_frame_start_time_.reset();
-}
-
-void WebFrameWidgetBase::ApplyViewportChanges(
-    const ApplyViewportChangesArgs& args) {
-  // Viewport changes only change the main frame.
-  if (!ForMainFrame())
-    return;
-  View()->ApplyViewportChanges(args);
-}
-
-void WebFrameWidgetBase::RecordManipulationTypeCounts(
-    cc::ManipulationInfo info) {
-  // Manipulation counts are only recorded for the main frame.
-  if (!ForMainFrame())
-    return;
-  if ((info & cc::kManipulationInfoWheel) == cc::kManipulationInfoWheel) {
-    UseCounter::Count(LocalRootImpl()->GetDocument(),
-                      WebFeature::kScrollByWheel);
-  }
-  if ((info & cc::kManipulationInfoTouch) == cc::kManipulationInfoTouch) {
-    UseCounter::Count(LocalRootImpl()->GetDocument(),
-                      WebFeature::kScrollByTouch);
-  }
-  if ((info & cc::kManipulationInfoPinchZoom) ==
-      cc::kManipulationInfoPinchZoom) {
-    UseCounter::Count(LocalRootImpl()->GetDocument(), WebFeature::kPinchZoom);
-  }
-  if ((info & cc::kManipulationInfoPrecisionTouchPad) ==
-      cc::kManipulationInfoPrecisionTouchPad) {
-    UseCounter::Count(LocalRootImpl()->GetDocument(),
-                      WebFeature::kScrollByPrecisionTouchPad);
-  }
-}
-
-void WebFrameWidgetBase::RecordDispatchRafAlignedInputTime(
-    base::TimeTicks raf_aligned_input_start_time) {
-  if (LocalRootImpl()) {
-    LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
-        LocalFrameUkmAggregator::kHandleInputEvents,
-        raf_aligned_input_start_time, base::TimeTicks::Now());
-  }
-}
-
-void WebFrameWidgetBase::SetSuppressFrameRequestsWorkaroundFor704763Only(
-    bool suppress_frame_requests) {
-  GetPage()->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only(
-      suppress_frame_requests);
-}
-
-std::unique_ptr<cc::BeginMainFrameMetrics>
-WebFrameWidgetBase::GetBeginMainFrameMetrics() {
-  if (!LocalRootImpl())
-    return nullptr;
-
-  return LocalRootImpl()
-      ->GetFrame()
-      ->View()
-      ->EnsureUkmAggregator()
-      .GetBeginMainFrameMetrics();
-}
-
-std::unique_ptr<cc::WebVitalMetrics> WebFrameWidgetBase::GetWebVitalMetrics() {
-  if (!LocalRootImpl())
-    return nullptr;
-
-  // This class should be called at most once per commit.
-  WebPerformance perf = LocalRootImpl()->Performance();
-  auto metrics = std::make_unique<cc::WebVitalMetrics>();
-  if (perf.FirstInputDelay().has_value())
-    metrics->first_input_delay = *perf.FirstInputDelay();
-
-  base::TimeTicks start = perf.NavigationStartAsMonotonicTime();
-  base::TimeTicks largest_contentful_paint =
-      perf.LargestContentfulPaintAsMonotonicTime();
-  if (largest_contentful_paint >= start)
-    metrics->largest_contentful_paint = largest_contentful_paint - start;
-
-  double layout_shift = LocalRootImpl()
-                            ->GetFrame()
-                            ->View()
-                            ->GetLayoutShiftTracker()
-                            .WeightedScore();
-  if (layout_shift > 0.f)
-    metrics->layout_shift = layout_shift;
-  return metrics;
-}
-
-void WebFrameWidgetBase::BeginUpdateLayers() {
-  if (LocalRootImpl())
-    update_layers_start_time_.emplace(base::TimeTicks::Now());
-}
-
-void WebFrameWidgetBase::EndUpdateLayers() {
-  if (LocalRootImpl()) {
-    DCHECK(update_layers_start_time_);
-    LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
-        LocalFrameUkmAggregator::kUpdateLayers,
-        update_layers_start_time_.value(), base::TimeTicks::Now());
-    probe::LayerTreeDidChange(LocalRootImpl()->GetFrame());
-  }
-  update_layers_start_time_.reset();
-}
-
-void WebFrameWidgetBase::RecordStartOfFrameMetrics() {
-  if (!LocalRootImpl())
-    return;
-
-  LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().BeginMainFrame();
-}
-
-void WebFrameWidgetBase::RecordEndOfFrameMetrics(
-    base::TimeTicks frame_begin_time,
-    cc::ActiveFrameSequenceTrackers trackers) {
-  if (!LocalRootImpl())
-    return;
-
-  LocalRootImpl()
-      ->GetFrame()
-      ->View()
-      ->EnsureUkmAggregator()
-      .RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now(),
-                               trackers);
-}
-
-bool WebFrameWidgetBase::WillHandleGestureEvent(const WebGestureEvent& event) {
-  possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kTouch;
-  possible_drag_event_info_.location =
-      gfx::ToFlooredPoint(event.PositionInScreen());
-
-  bool move_cursor = false;
-  switch (event.GetType()) {
-    case WebInputEvent::Type::kGestureScrollBegin: {
-      if (event.data.scroll_begin.cursor_control) {
-        swipe_to_move_cursor_activated_ = true;
-        move_cursor = true;
-      }
-      break;
-    }
-    case WebInputEvent::Type::kGestureScrollUpdate: {
-      if (swipe_to_move_cursor_activated_)
-        move_cursor = true;
-      break;
-    }
-    case WebInputEvent::Type::kGestureScrollEnd: {
-      if (swipe_to_move_cursor_activated_) {
-        swipe_to_move_cursor_activated_ = false;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-  // TODO(crbug.com/1140106): Place cursor for scroll begin other than just move
-  // cursor.
-  if (move_cursor) {
-    WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-    if (focused_frame) {
-      gfx::Point base(event.PositionInWidget().x(),
-                      event.PositionInWidget().y());
-      focused_frame->MoveCaretSelection(base);
-    }
-    return true;
-  }
-  return false;
-}
-
-void WebFrameWidgetBase::WillHandleMouseEvent(const WebMouseEvent& event) {
-  possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kMouse;
-  possible_drag_event_info_.location =
-      gfx::Point(event.PositionInScreen().x(), event.PositionInScreen().y());
-}
-
-void WebFrameWidgetBase::ObserveGestureEventAndResult(
-    const WebGestureEvent& gesture_event,
-    const gfx::Vector2dF& unused_delta,
-    const cc::OverscrollBehavior& overscroll_behavior,
-    bool event_processed) {
-  if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
-    return;
-
-  cc::InputHandlerScrollResult scroll_result;
-  scroll_result.did_scroll = event_processed;
-  scroll_result.did_overscroll_root = !unused_delta.IsZero();
-  scroll_result.unused_scroll_delta = unused_delta;
-  scroll_result.overscroll_behavior = overscroll_behavior;
-
-  widget_base_->widget_input_handler_manager()->ObserveGestureEventOnMainThread(
-      gesture_event, scroll_result);
-}
-
-void WebFrameWidgetBase::DidHandleKeyEvent() {
-  ClearEditCommands();
-}
-
-WebTextInputType WebFrameWidgetBase::GetTextInputType() {
-  if (ShouldDispatchImeEventsToPlugin()) {
-    return GetFocusedPluginContainer()->GetPluginTextInputType();
-  }
-
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return WebTextInputType::kWebTextInputTypeNone;
-  return controller->TextInputType();
-}
-
-void WebFrameWidgetBase::SetCursorVisibilityState(bool is_visible) {
-  GetPage()->SetIsCursorVisible(is_visible);
-}
-
-void WebFrameWidgetBase::ApplyViewportChangesForTesting(
-    const ApplyViewportChangesArgs& args) {
-  widget_base_->ApplyViewportChanges(args);
-}
-
-void WebFrameWidgetBase::SetDisplayMode(mojom::blink::DisplayMode mode) {
-  if (mode != display_mode_) {
-    display_mode_ = mode;
-    LocalFrame* frame = LocalRootImpl()->GetFrame();
-    frame->MediaQueryAffectingValueChangedForLocalSubtree(
-        MediaValueChange::kOther);
-  }
-}
-
-void WebFrameWidgetBase::SetWindowSegments(
-    const std::vector<gfx::Rect>& window_segments_param) {
-  WebVector<gfx::Rect> window_segments(window_segments_param);
-  if (!window_segments_.Equals(window_segments)) {
-    window_segments_ = window_segments;
-    LocalFrame* frame = LocalRootImpl()->GetFrame();
-    frame->WindowSegmentsChanged(window_segments_);
-
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const std::vector<gfx::Rect>& window_segments,
-           RemoteFrame* remote_frame) {
-          remote_frame->Client()->DidChangeRootWindowSegments(window_segments);
-        },
-        window_segments_param));
-  }
-}
-
-void WebFrameWidgetBase::SetCursor(const ui::Cursor& cursor) {
-  widget_base_->SetCursor(cursor);
-}
-
-bool WebFrameWidgetBase::HandlingInputEvent() {
-  return widget_base_->input_handler().handling_input_event();
-}
-
-void WebFrameWidgetBase::SetHandlingInputEvent(bool handling) {
-  widget_base_->input_handler().set_handling_input_event(handling);
-}
-
-void WebFrameWidgetBase::ProcessInputEventSynchronouslyForTesting(
-    const WebCoalescedInputEvent& event,
-    HandledEventCallback callback) {
-  widget_base_->input_handler().HandleInputEvent(event, nullptr,
-                                                 std::move(callback));
-}
-
-WebInputEventResult WebFrameWidgetBase::DispatchBufferedTouchEvents() {
-  CHECK(LocalRootImpl());
-
-  if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
-    devtools->DispatchBufferedTouchEvents();
-
-  return LocalRootImpl()
-      ->GetFrame()
-      ->GetEventHandler()
-      .DispatchBufferedTouchEvents();
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleInputEvent(
-    const WebCoalescedInputEvent& coalesced_event) {
-  const WebInputEvent& input_event = coalesced_event.Event();
-  TRACE_EVENT1("input,rail", "WebFrameWidgetBase::HandleInputEvent", "type",
-               WebInputEvent::GetName(input_event.GetType()));
-  DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
-  CHECK(LocalRootImpl());
-
-  // Only record metrics for the main frame.
-  if (ForMainFrame()) {
-    GetPage()->GetVisualViewport().StartTrackingPinchStats();
-  }
-
-  // If a drag-and-drop operation is in progress, ignore input events except
-  // PointerCancel.
-  if (doing_drag_and_drop_ &&
-      input_event.GetType() != WebInputEvent::Type::kPointerCancel)
-    return WebInputEventResult::kHandledSuppressed;
-
-  // Don't handle events once we've started shutting down.
-  if (!GetPage())
-    return WebInputEventResult::kNotHandled;
-
-  if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) {
-    auto result = devtools->HandleInputEvent(input_event);
-    if (result != WebInputEventResult::kNotHandled)
-      return result;
-  }
-
-  // Report the event to be NOT processed by WebKit, so that the browser can
-  // handle it appropriately.
-  if (IgnoreInputEvents())
-    return WebInputEventResult::kNotHandled;
-
-  base::AutoReset<const WebInputEvent*> current_event_change(
-      &CurrentInputEvent::current_input_event_, &input_event);
-  UIEventWithKeyState::ClearNewTabModifierSetFromIsolatedWorld();
-
-  if (GetPage()->GetPointerLockController().IsPointerLocked() &&
-      WebInputEvent::IsMouseEventType(input_event.GetType())) {
-    PointerLockMouseEvent(coalesced_event);
-    return WebInputEventResult::kHandledSystem;
-  }
-
-  /// These metrics are only captured for the main frame.
-  if (ForMainFrame()) {
-    Document& main_frame_document = *LocalRootImpl()->GetFrame()->GetDocument();
-
-    if (input_event.GetType() != WebInputEvent::Type::kMouseMove) {
-      FirstMeaningfulPaintDetector::From(main_frame_document)
-          .NotifyInputEvent();
-    }
-
-    if (input_event.GetType() != WebInputEvent::Type::kMouseMove &&
-        input_event.GetType() != WebInputEvent::Type::kMouseEnter &&
-        input_event.GetType() != WebInputEvent::Type::kMouseLeave) {
-      InteractiveDetector* interactive_detector(
-          InteractiveDetector::From(main_frame_document));
-      if (interactive_detector) {
-        interactive_detector->OnInvalidatingInputEvent(input_event.TimeStamp());
-      }
-    }
-  }
-
-  NotifyInputObservers(coalesced_event);
-
-  // Notify the focus frame of the input. Note that the other frames are not
-  // notified as input is only handled by the focused frame.
-  Frame* frame = FocusedCoreFrame();
-  if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
-    if (auto* content_capture_manager =
-            local_frame->LocalFrameRoot().GetContentCaptureManager()) {
-      content_capture_manager->NotifyInputEvent(input_event.GetType(),
-                                                *local_frame);
-    }
-  }
-
-  // Skip the pointerrawupdate for mouse capture case.
-  if (mouse_capture_element_ &&
-      input_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)
-    return WebInputEventResult::kHandledSystem;
-
-  if (mouse_capture_element_ &&
-      WebInputEvent::IsMouseEventType(input_event.GetType()))
-    return HandleCapturedMouseEvent(coalesced_event);
-
-  // FIXME: This should take in the intended frame, not the local frame
-  // root.
-  return PageWidgetDelegate::HandleInputEvent(*this, coalesced_event,
-                                              LocalRootImpl()->GetFrame());
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleCapturedMouseEvent(
-    const WebCoalescedInputEvent& coalesced_event) {
-  const WebInputEvent& input_event = coalesced_event.Event();
-  TRACE_EVENT1("input", "captured mouse event", "type", input_event.GetType());
-  // Save |mouse_capture_element_| since |MouseCaptureLost()| will clear it.
-  HTMLPlugInElement* element = mouse_capture_element_;
-
-  // Not all platforms call mouseCaptureLost() directly.
-  if (input_event.GetType() == WebInputEvent::Type::kMouseUp) {
-    SetMouseCapture(false);
-    MouseCaptureLost();
-  }
-
-  AtomicString event_type;
-  switch (input_event.GetType()) {
-    case WebInputEvent::Type::kMouseEnter:
-      event_type = event_type_names::kMouseover;
-      break;
-    case WebInputEvent::Type::kMouseMove:
-      event_type = event_type_names::kMousemove;
-      break;
-    case WebInputEvent::Type::kPointerRawUpdate:
-      // There will be no mouse event for rawupdate events.
-      event_type = event_type_names::kPointerrawupdate;
-      break;
-    case WebInputEvent::Type::kMouseLeave:
-      event_type = event_type_names::kMouseout;
-      break;
-    case WebInputEvent::Type::kMouseDown:
-      event_type = event_type_names::kMousedown;
-      LocalFrame::NotifyUserActivation(
-          element->GetDocument().GetFrame(),
-          mojom::blink::UserActivationNotificationType::kInteraction);
-      break;
-    case WebInputEvent::Type::kMouseUp:
-      event_type = event_type_names::kMouseup;
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  WebMouseEvent transformed_event =
-      TransformWebMouseEvent(LocalRootImpl()->GetFrameView(),
-                             static_cast<const WebMouseEvent&>(input_event));
-  if (LocalFrame* frame = element->GetDocument().GetFrame()) {
-    frame->GetEventHandler().HandleTargetedMouseEvent(
-        element, transformed_event, event_type,
-        TransformWebMouseEventVector(
-            LocalRootImpl()->GetFrameView(),
-            coalesced_event.GetCoalescedEventsPointers()),
-        TransformWebMouseEventVector(
-            LocalRootImpl()->GetFrameView(),
-            coalesced_event.GetPredictedEventsPointers()));
-  }
-  return WebInputEventResult::kHandledSystem;
-}
-
-void WebFrameWidgetBase::UpdateTextInputState() {
-  widget_base_->UpdateTextInputState();
-}
-
-void WebFrameWidgetBase::UpdateSelectionBounds() {
-  widget_base_->UpdateSelectionBounds();
-}
-
-void WebFrameWidgetBase::ShowVirtualKeyboard() {
-  widget_base_->ShowVirtualKeyboard();
-}
-
-void WebFrameWidgetBase::FlushInputProcessedCallback() {
-  widget_base_->FlushInputProcessedCallback();
-}
-
-void WebFrameWidgetBase::CancelCompositionForPepper() {
-  widget_base_->CancelCompositionForPepper();
-}
-
-void WebFrameWidgetBase::RequestMouseLock(
-    bool has_transient_user_activation,
-    bool request_unadjusted_movement,
-    mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback) {
-  mojom::blink::WidgetInputHandlerHost* host =
-      widget_base_->widget_input_handler_manager()->GetWidgetInputHandlerHost();
-
-  // If we don't have a host just leave the callback uncalled. This simulates
-  // the browser indefinitely postponing the mouse request which is valid.
-  // Note that |callback| is not a mojo bound callback (until it is passed
-  // into the mojo interface) and can be destructed without invoking the
-  // callback. It does share the same signature as the mojo definition
-  // for simplicity.
-  if (host) {
-    host->RequestMouseLock(has_transient_user_activation,
-                           request_unadjusted_movement, std::move(callback));
-  }
-}
-
-void WebFrameWidgetBase::MouseCaptureLost() {
-  TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
-                                  TRACE_ID_LOCAL(this));
-  mouse_capture_element_ = nullptr;
-}
-
-void WebFrameWidgetBase::ApplyVisualProperties(
-    const VisualProperties& visual_properties) {
-  widget_base_->UpdateVisualProperties(visual_properties);
-}
-
-bool WebFrameWidgetBase::IsFullscreenGranted() {
-  return is_fullscreen_granted_;
-}
-
-bool WebFrameWidgetBase::PinchGestureActiveInMainFrame() {
-  return is_pinch_gesture_active_in_mainframe_;
-}
-
-float WebFrameWidgetBase::PageScaleInMainFrame() {
-  return page_scale_factor_in_mainframe_;
-}
-
-void WebFrameWidgetBase::UpdateSurfaceAndScreenInfo(
-    const viz::LocalSurfaceId& new_local_surface_id,
-    const gfx::Rect& compositor_viewport_pixel_rect,
-    const ScreenInfo& new_screen_info) {
-  widget_base_->UpdateSurfaceAndScreenInfo(
-      new_local_surface_id, compositor_viewport_pixel_rect, new_screen_info);
-}
-
-void WebFrameWidgetBase::UpdateScreenInfo(const ScreenInfo& new_screen_info) {
-  widget_base_->UpdateScreenInfo(new_screen_info);
-}
-
-void WebFrameWidgetBase::UpdateSurfaceAndCompositorRect(
-    const viz::LocalSurfaceId& new_local_surface_id,
-    const gfx::Rect& compositor_viewport_pixel_rect) {
-  widget_base_->UpdateSurfaceAndCompositorRect(new_local_surface_id,
-                                               compositor_viewport_pixel_rect);
-}
-
-void WebFrameWidgetBase::UpdateCompositorViewportRect(
-    const gfx::Rect& compositor_viewport_pixel_rect) {
-  widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
-}
-
-const ScreenInfo& WebFrameWidgetBase::GetScreenInfo() {
-  return widget_base_->GetScreenInfo();
-}
-
-gfx::Rect WebFrameWidgetBase::WindowRect() {
-  return widget_base_->WindowRect();
-}
-
-gfx::Rect WebFrameWidgetBase::ViewRect() {
-  return widget_base_->ViewRect();
-}
-
-void WebFrameWidgetBase::SetScreenRects(const gfx::Rect& widget_screen_rect,
-                                        const gfx::Rect& window_screen_rect) {
-  widget_base_->SetScreenRects(widget_screen_rect, window_screen_rect);
-}
-
-gfx::Size WebFrameWidgetBase::VisibleViewportSizeInDIPs() {
-  return widget_base_->VisibleViewportSizeInDIPs();
-}
-
-void WebFrameWidgetBase::SetPendingWindowRect(
-    const gfx::Rect& window_screen_rect) {
-  widget_base_->SetPendingWindowRect(window_screen_rect);
-}
-
-void WebFrameWidgetBase::AckPendingWindowRect() {
-  widget_base_->AckPendingWindowRect();
-}
-
-bool WebFrameWidgetBase::IsHidden() const {
-  return widget_base_->is_hidden();
-}
-
-WebString WebFrameWidgetBase::GetLastToolTipTextForTesting() const {
-  return GetPage()->GetChromeClient().GetLastToolTipTextForTesting();
-}
-
-float WebFrameWidgetBase::GetEmulatorScale() {
-  if (device_emulator_)
-    return device_emulator_->scale();
-  return 1.0f;
-}
-
-void WebFrameWidgetBase::IntrinsicSizingInfoChanged(
-    mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
-  DCHECK(ForSubframe());
-  GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
-      std::move(sizing_info));
-}
-
-void WebFrameWidgetBase::AutoscrollStart(const gfx::PointF& position) {
-  GetAssociatedFrameWidgetHost()->AutoscrollStart(std::move(position));
-}
-
-void WebFrameWidgetBase::AutoscrollFling(const gfx::Vector2dF& velocity) {
-  GetAssociatedFrameWidgetHost()->AutoscrollFling(std::move(velocity));
-}
-
-void WebFrameWidgetBase::AutoscrollEnd() {
-  GetAssociatedFrameWidgetHost()->AutoscrollEnd();
-}
-
-void WebFrameWidgetBase::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
-  if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
-    NotifySwapAndPresentationTime(
-        base::NullCallback(),
-        WTF::Bind(&WebFrameWidgetBase::PresentationCallbackForMeaningfulLayout,
-                  WrapPersistent(this)));
-  }
-
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating(
-          [](WebMeaningfulLayout layout_type, WebLocalFrame* local_frame) {
-            local_frame->Client()->DidMeaningfulLayout(layout_type);
-          },
-          layout_type));
-}
-
-void WebFrameWidgetBase::PresentationCallbackForMeaningfulLayout(
-    blink::WebSwapResult,
-    base::TimeTicks) {
-  GetAssociatedFrameWidgetHost()->DidFirstVisuallyNonEmptyPaint();
-}
-
-void WebFrameWidgetBase::RequestAnimationAfterDelay(
-    const base::TimeDelta& delay) {
-  DCHECK(request_animation_after_delay_timer_.get());
-  if (request_animation_after_delay_timer_->IsActive() &&
-      request_animation_after_delay_timer_->NextFireInterval() > delay) {
-    request_animation_after_delay_timer_->Stop();
-  }
-  if (!request_animation_after_delay_timer_->IsActive()) {
-    request_animation_after_delay_timer_->StartOneShot(delay, FROM_HERE);
-  }
-}
-
-void WebFrameWidgetBase::SetRootLayer(scoped_refptr<cc::Layer> layer) {
-  if (!View()->does_composite()) {
-    DCHECK(ForMainFrame());
-    DCHECK(!layer);
-    return;
-  }
-
-  // Set up some initial state before we are setting the layer.
-  if (ForSubframe() && layer) {
-    // Child local roots will always have a transparent background color.
-    widget_base_->LayerTreeHost()->set_background_color(SK_ColorTRANSPARENT);
-    // Pass the limits even though this is for subframes, as the limits will
-    // be needed in setting the raster scale.
-    SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
-                               View()->MinimumPageScaleFactor(),
-                               View()->MaximumPageScaleFactor());
-  }
-
-  bool root_layer_exists = !!layer;
-  widget_base_->LayerTreeHost()->SetRootLayer(std::move(layer));
-
-  // Notify the WebView that we did set a layer.
-  if (ForMainFrame()) {
-    View()->DidChangeRootLayer(root_layer_exists);
-  }
-}
-
-void WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired(TimerBase*) {
-  if (client_)
-    client_->ScheduleAnimation();
-}
-
-base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
-WebFrameWidgetBase::EnsureCompositorMutatorDispatcher(
-    scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner) {
-  if (!mutator_task_runner_) {
-    widget_base_->LayerTreeHost()->SetLayerTreeMutator(
-        AnimationWorkletMutatorDispatcherImpl::CreateCompositorThreadClient(
-            &mutator_dispatcher_, &mutator_task_runner_));
-  }
-
-  DCHECK(mutator_task_runner_);
-  *mutator_task_runner = mutator_task_runner_;
-  return mutator_dispatcher_;
-}
-
-HitTestResult WebFrameWidgetBase::CoreHitTestResultAt(
-    const gfx::PointF& point_in_viewport) {
-  LocalFrameView* view = LocalRootImpl()->GetFrameView();
-  FloatPoint point_in_root_frame(
-      view->ViewportToFrame(FloatPoint(point_in_viewport)));
-  return HitTestResultForRootFramePos(point_in_root_frame);
-}
-
-cc::AnimationHost* WebFrameWidgetBase::AnimationHost() const {
-  return widget_base_->AnimationHost();
-}
-
-base::WeakPtr<PaintWorkletPaintDispatcher>
-WebFrameWidgetBase::EnsureCompositorPaintDispatcher(
-    scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner) {
-  // We check paint_task_runner_ not paint_dispatcher_ because the dispatcher is
-  // a base::WeakPtr that should only be used on the compositor thread.
-  if (!paint_task_runner_) {
-    widget_base_->LayerTreeHost()->SetPaintWorkletLayerPainter(
-        PaintWorkletPaintDispatcher::CreateCompositorThreadPainter(
-            &paint_dispatcher_));
-    paint_task_runner_ = Thread::CompositorThread()->GetTaskRunner();
-  }
-  DCHECK(paint_task_runner_);
-  *paint_task_runner = paint_task_runner_;
-  return paint_dispatcher_;
-}
-
-void WebFrameWidgetBase::SetDelegatedInkMetadata(
-    std::unique_ptr<viz::DelegatedInkMetadata> metadata) {
-  widget_base_->LayerTreeHost()->SetDelegatedInkMetadata(std::move(metadata));
-}
-
-// Enables measuring and reporting both presentation times and swap times in
-// swap promises.
-class ReportTimeSwapPromise : public cc::SwapPromise {
- public:
-  ReportTimeSwapPromise(WebReportTimeCallback swap_time_callback,
-                        WebReportTimeCallback presentation_time_callback,
-                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-                        WebFrameWidgetBase* widget)
-      : swap_time_callback_(std::move(swap_time_callback)),
-        presentation_time_callback_(std::move(presentation_time_callback)),
-        task_runner_(std::move(task_runner)),
-        widget_(widget) {}
-  ~ReportTimeSwapPromise() override = default;
-
-  void DidActivate() override {}
-
-  void WillSwap(viz::CompositorFrameMetadata* metadata) override {
-    DCHECK_GT(metadata->frame_token, 0u);
-    // The interval between the current swap and its presentation time is
-    // reported in UMA (see corresponding code in DidSwap() below).
-    frame_token_ = metadata->frame_token;
-  }
-
-  void DidSwap() override {
-    DCHECK_GT(frame_token_, 0u);
-    PostCrossThreadTask(
-        *task_runner_, FROM_HERE,
-        CrossThreadBindOnce(
-            &RunCallbackAfterSwap, widget_, base::TimeTicks::Now(),
-            std::move(swap_time_callback_),
-            std::move(presentation_time_callback_), frame_token_));
-  }
-
-  cc::SwapPromise::DidNotSwapAction DidNotSwap(
-      DidNotSwapReason reason) override {
-    WebSwapResult result;
-    switch (reason) {
-      case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
-        result = WebSwapResult::kDidNotSwapSwapFails;
-        break;
-      case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
-        result = WebSwapResult::kDidNotSwapCommitFails;
-        break;
-      case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
-        result = WebSwapResult::kDidNotSwapCommitNoUpdate;
-        break;
-      case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
-        result = WebSwapResult::kDidNotSwapActivationFails;
-        break;
-    }
-    // During a failed swap, return the current time regardless of whether we're
-    // using presentation or swap timestamps.
-    PostCrossThreadTask(
-        *task_runner_, FROM_HERE,
-        CrossThreadBindOnce(
-            [](WebSwapResult result, base::TimeTicks swap_time,
-               WebReportTimeCallback swap_time_callback,
-               WebReportTimeCallback presentation_time_callback) {
-              ReportTime(std::move(swap_time_callback), result, swap_time);
-              ReportTime(std::move(presentation_time_callback), result,
-                         swap_time);
-            },
-            result, base::TimeTicks::Now(), std::move(swap_time_callback_),
-            std::move(presentation_time_callback_)));
-    return DidNotSwapAction::BREAK_PROMISE;
-  }
-
-  int64_t TraceId() const override { return 0; }
-
- private:
-  static void RunCallbackAfterSwap(
-      WebFrameWidgetBase* widget,
-      base::TimeTicks swap_time,
-      WebReportTimeCallback swap_time_callback,
-      WebReportTimeCallback presentation_time_callback,
-      int frame_token) {
-    // If the widget was collected or the widget wasn't collected yet, but
-    // it was closed don't schedule a presentation callback.
-    if (widget && widget->widget_base_) {
-      widget->widget_base_->AddPresentationCallback(
-          frame_token,
-          WTF::Bind(&RunCallbackAfterPresentation,
-                    std::move(presentation_time_callback), swap_time));
-      ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
-                 swap_time);
-    } else {
-      ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
-                 swap_time);
-      ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
-                 swap_time);
-    }
-  }
-
-  static void RunCallbackAfterPresentation(
-      WebReportTimeCallback presentation_time_callback,
-      base::TimeTicks swap_time,
-      base::TimeTicks presentation_time) {
-    DCHECK(!swap_time.is_null());
-    bool presentation_time_is_valid =
-        !presentation_time.is_null() && (presentation_time > swap_time);
-    UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
-                          presentation_time_is_valid);
-    if (presentation_time_is_valid) {
-      // This measures from 1ms to 10seconds.
-      UMA_HISTOGRAM_TIMES(
-          "PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime",
-          presentation_time - swap_time);
-    }
-    ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
-               presentation_time_is_valid ? presentation_time : swap_time);
-  }
-
-  static void ReportTime(WebReportTimeCallback callback,
-                         WebSwapResult result,
-                         base::TimeTicks time) {
-    if (callback)
-      std::move(callback).Run(result, time);
-  }
-
-  WebReportTimeCallback swap_time_callback_;
-  WebReportTimeCallback presentation_time_callback_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  CrossThreadWeakPersistent<WebFrameWidgetBase> widget_;
-  uint32_t frame_token_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
-};
-
-void WebFrameWidgetBase::NotifySwapAndPresentationTimeInBlink(
-    WebReportTimeCallback swap_time_callback,
-    WebReportTimeCallback presentation_time_callback) {
-  NotifySwapAndPresentationTime(std::move(swap_time_callback),
-                                std::move(presentation_time_callback));
-}
-
-void WebFrameWidgetBase::NotifySwapAndPresentationTime(
-    WebReportTimeCallback swap_time_callback,
-    WebReportTimeCallback presentation_time_callback) {
-  if (!View()->does_composite())
-    return;
-  widget_base_->LayerTreeHost()->QueueSwapPromise(
-      std::make_unique<ReportTimeSwapPromise>(
-          std::move(swap_time_callback), std::move(presentation_time_callback),
-          widget_base_->LayerTreeHost()
-              ->GetTaskRunnerProvider()
-              ->MainThreadTaskRunner(),
-          this));
-}
-
-scheduler::WebRenderWidgetSchedulingState*
-WebFrameWidgetBase::RendererWidgetSchedulingState() {
-  return widget_base_->RendererWidgetSchedulingState();
-}
-
-void WebFrameWidgetBase::WaitForDebuggerWhenShown() {
-  local_root_->WaitForDebuggerWhenShown();
-}
-
-void WebFrameWidgetBase::SetTextZoomFactor(float text_zoom_factor) {
-  local_root_->GetFrame()->SetTextZoomFactor(text_zoom_factor);
-}
-
-float WebFrameWidgetBase::TextZoomFactor() {
-  return local_root_->GetFrame()->TextZoomFactor();
-}
-
-void WebFrameWidgetBase::SetMainFrameOverlayColor(SkColor color) {
-  DCHECK(!local_root_->Parent());
-  local_root_->GetFrame()->SetMainFrameColorOverlay(color);
-}
-
-void WebFrameWidgetBase::AddEditCommandForNextKeyEvent(const WebString& name,
-                                                       const WebString& value) {
-  edit_commands_.push_back(mojom::blink::EditCommand::New(name, value));
-}
-
-bool WebFrameWidgetBase::HandleCurrentKeyboardEvent() {
-  bool did_execute_command = false;
-  WebLocalFrame* frame = FocusedWebLocalFrameInWidget();
-  if (!frame)
-    frame = local_root_;
-  for (const auto& command : edit_commands_) {
-    // In gtk and cocoa, it's possible to bind multiple edit commands to one
-    // key (but it's the exception). Once one edit command is not executed, it
-    // seems safest to not execute the rest.
-    if (!frame->ExecuteCommand(command->name, command->value))
-      break;
-    did_execute_command = true;
-  }
-
-  return did_execute_command;
-}
-
-void WebFrameWidgetBase::ClearEditCommands() {
-  edit_commands_ = Vector<mojom::blink::EditCommandPtr>();
-}
-
-WebTextInputInfo WebFrameWidgetBase::TextInputInfo() {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return WebTextInputInfo();
-  return controller->TextInputInfo();
-}
-
-ui::mojom::blink::VirtualKeyboardVisibilityRequest
-WebFrameWidgetBase::GetLastVirtualKeyboardVisibilityRequest() {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE;
-  return controller->GetLastVirtualKeyboardVisibilityRequest();
-}
-
-bool WebFrameWidgetBase::ShouldSuppressKeyboardForFocusedElement() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return false;
-  return focused_frame->ShouldSuppressKeyboardForFocusedElement();
-}
-
-void WebFrameWidgetBase::GetEditContextBoundsInWindow(
-    base::Optional<gfx::Rect>* edit_context_control_bounds,
-    base::Optional<gfx::Rect>* edit_context_selection_bounds) {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return;
-  WebRect control_bounds;
-  WebRect selection_bounds;
-  controller->GetLayoutBounds(&control_bounds, &selection_bounds);
-  *edit_context_control_bounds =
-      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(control_bounds));
-  if (controller->IsEditContextActive()) {
-    *edit_context_selection_bounds =
-        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(selection_bounds));
-  }
-}
-
-int32_t WebFrameWidgetBase::ComputeWebTextInputNextPreviousFlags() {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return 0;
-  return controller->ComputeWebTextInputNextPreviousFlags();
-}
-
-void WebFrameWidgetBase::ResetVirtualKeyboardVisibilityRequest() {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return;
-  controller->SetVirtualKeyboardVisibilityRequest(
-      ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE);
-  ;
-}
-
-bool WebFrameWidgetBase::GetSelectionBoundsInWindow(
-    gfx::Rect* focus,
-    gfx::Rect* anchor,
-    base::i18n::TextDirection* focus_dir,
-    base::i18n::TextDirection* anchor_dir,
-    bool* is_anchor_first) {
-  if (ShouldDispatchImeEventsToPlugin()) {
-    // TODO(kinaba) http://crbug.com/101101
-    // Current Pepper IME API does not handle selection bounds. So we simply
-    // use the caret position as an empty range for now. It will be updated
-    // after Pepper API equips features related to surrounding text retrieval.
-    gfx::Rect pepper_caret_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
-        GetFocusedPluginContainer()->GetPluginCaretBounds());
-    if (pepper_caret_in_dips == *focus && pepper_caret_in_dips == *anchor)
-      return false;
-    *focus = pepper_caret_in_dips;
-    *anchor = *focus;
-    return true;
-  }
-  gfx::Rect focus_root_frame;
-  gfx::Rect anchor_root_frame;
-  CalculateSelectionBounds(focus_root_frame, anchor_root_frame);
-  gfx::Rect focus_rect_in_dips =
-      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(focus_root_frame));
-  gfx::Rect anchor_rect_in_dips =
-      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(anchor_root_frame));
-
-  // if the bounds are the same return false.
-  if (focus_rect_in_dips == *focus && anchor_rect_in_dips == *anchor)
-    return false;
-  *focus = focus_rect_in_dips;
-  *anchor = anchor_rect_in_dips;
-
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return true;
-  focused_frame->SelectionTextDirection(*focus_dir, *anchor_dir);
-  *is_anchor_first = focused_frame->IsSelectionAnchorFirst();
-  return true;
-}
-
-void WebFrameWidgetBase::ClearTextInputState() {
-  widget_base_->ClearTextInputState();
-}
-
-bool WebFrameWidgetBase::IsPasting() {
-  return widget_base_->is_pasting();
-}
-
-bool WebFrameWidgetBase::HandlingSelectRange() {
-  return widget_base_->handling_select_range();
-}
-
-void WebFrameWidgetBase::SetFocus(bool focus) {
-  widget_base_->SetFocus(focus);
-}
-
-bool WebFrameWidgetBase::HasFocus() {
-  return widget_base_->has_focus();
-}
-
-void WebFrameWidgetBase::SetToolTipText(const String& tooltip_text,
-                                        TextDirection dir) {
-  widget_base_->SetToolTipText(tooltip_text, dir);
-}
-
-void WebFrameWidgetBase::DidOverscroll(
-    const gfx::Vector2dF& overscroll_delta,
-    const gfx::Vector2dF& accumulated_overscroll,
-    const gfx::PointF& position,
-    const gfx::Vector2dF& velocity) {
-#if defined(OS_MAC)
-  // On OSX the user can disable the elastic overscroll effect. If that's the
-  // case, don't forward the overscroll notification.
-  if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
-    return;
-#endif
-
-  cc::OverscrollBehavior overscroll_behavior =
-      widget_base_->LayerTreeHost()->overscroll_behavior();
-  if (!widget_base_->input_handler().DidOverscrollFromBlink(
-          overscroll_delta, accumulated_overscroll, position, velocity,
-          overscroll_behavior))
-    return;
-
-  // If we're currently handling an event, stash the overscroll data such that
-  // it can be bundled in the event ack.
-  if (mojom::blink::WidgetInputHandlerHost* host =
-          widget_base_->widget_input_handler_manager()
-              ->GetWidgetInputHandlerHost()) {
-    host->DidOverscroll(mojom::blink::DidOverscrollParams::New(
-        accumulated_overscroll, overscroll_delta, velocity, position,
-        overscroll_behavior));
-  }
-}
-
-void WebFrameWidgetBase::InjectGestureScrollEvent(
-    blink::WebGestureDevice device,
-    const gfx::Vector2dF& delta,
-    ui::ScrollGranularity granularity,
-    cc::ElementId scrollable_area_element_id,
-    blink::WebInputEvent::Type injected_type) {
-  if (RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
-    // create a GestureScroll Event and post it to the compositor thread
-    // TODO(crbug.com/1126098) use original input event's timestamp.
-    // TODO(crbug.com/1082590) ensure continuity in scroll metrics collection
-    base::TimeTicks now = base::TimeTicks::Now();
-    std::unique_ptr<WebGestureEvent> gesture_event =
-        WebGestureEvent::GenerateInjectedScrollGesture(
-            injected_type, now, device, gfx::PointF(0, 0), delta, granularity);
-    if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
-      gesture_event->data.scroll_begin.scrollable_area_element_id =
-          scrollable_area_element_id.GetStableId();
-      gesture_event->data.scroll_begin.main_thread_hit_tested = true;
-    }
-
-    widget_base_->widget_input_handler_manager()
-        ->DispatchScrollGestureToCompositor(std::move(gesture_event));
-  } else {
-    widget_base_->input_handler().InjectGestureScrollEvent(
-        device, delta, granularity, scrollable_area_element_id, injected_type);
-  }
-}
-
-void WebFrameWidgetBase::DidChangeCursor(const ui::Cursor& cursor) {
-  widget_base_->SetCursor(cursor);
-  Client()->DidChangeCursor(cursor);
-}
-
-bool WebFrameWidgetBase::SetComposition(
-    const String& text,
-    const Vector<ui::ImeTextSpan>& ime_text_spans,
-    const gfx::Range& replacement_range,
-    int selection_start,
-    int selection_end) {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return false;
-
-  return controller->SetComposition(
-      text, ime_text_spans,
-      replacement_range.IsValid()
-          ? WebRange(replacement_range.start(), replacement_range.length())
-          : WebRange(),
-      selection_start, selection_end);
-}
-
-void WebFrameWidgetBase::CommitText(
-    const String& text,
-    const Vector<ui::ImeTextSpan>& ime_text_spans,
-    const gfx::Range& replacement_range,
-    int relative_cursor_pos) {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return;
-  controller->CommitText(
-      text, ime_text_spans,
-      replacement_range.IsValid()
-          ? WebRange(replacement_range.start(), replacement_range.length())
-          : WebRange(),
-      relative_cursor_pos);
-}
-
-void WebFrameWidgetBase::FinishComposingText(bool keep_selection) {
-  WebInputMethodController* controller = GetActiveWebInputMethodController();
-  if (!controller)
-    return;
-  controller->FinishComposingText(
-      keep_selection ? WebInputMethodController::kKeepSelection
-                     : WebInputMethodController::kDoNotKeepSelection);
-}
-
-bool WebFrameWidgetBase::IsProvisional() {
-  return LocalRoot()->IsProvisional();
-}
-
-uint64_t WebFrameWidgetBase::GetScrollableContainerIdAt(
-    const gfx::PointF& point_in_dips) {
-  gfx::PointF point = widget_base_->DIPsToBlinkSpace(point_in_dips);
-  return HitTestResultAt(point).GetScrollableContainerId();
-}
-
-bool WebFrameWidgetBase::ShouldHandleImeEvents() {
-  if (ForMainFrame()) {
-    return HasFocus();
-  } else {
-    // TODO(ekaramad): main frame widget returns true only if it has focus.
-    // We track page focus in all WebViews on the page but the WebFrameWidgets
-    // corresponding to child local roots do not get the update. For now, this
-    // method returns true when the WebFrameWidget is for a child local frame,
-    // i.e., IME events will be processed regardless of page focus. We should
-    // revisit this after page focus for OOPIFs has been fully resolved
-    // (https://crbug.com/689777).
-    return LocalRootImpl();
-  }
-}
-
-void WebFrameWidgetBase::SetEditCommandsForNextKeyEvent(
-    Vector<mojom::blink::EditCommandPtr> edit_commands) {
-  edit_commands_ = std::move(edit_commands);
-}
-
-void WebFrameWidgetBase::FocusChangeComplete() {
-  blink::WebLocalFrame* focused = LocalRoot()->View()->FocusedFrame();
-
-  if (focused && focused->AutofillClient())
-    focused->AutofillClient()->DidCompleteFocusChangeInFrame();
-}
-
-void WebFrameWidgetBase::ShowVirtualKeyboardOnElementFocus() {
-  widget_base_->ShowVirtualKeyboardOnElementFocus();
-}
-
-void WebFrameWidgetBase::ProcessTouchAction(WebTouchAction touch_action) {
-  widget_base_->ProcessTouchAction(touch_action);
-}
-
-void WebFrameWidgetBase::DidHandleGestureEvent(const WebGestureEvent& event) {
-#if defined(OS_ANDROID) || defined(USE_AURA)
-  if (event.GetType() == WebInputEvent::Type::kGestureTap) {
-    widget_base_->ShowVirtualKeyboard();
-  } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) {
-    WebInputMethodController* controller = GetActiveWebInputMethodController();
-    if (!controller || controller->TextInputInfo().value.IsEmpty())
-      widget_base_->UpdateTextInputState();
-    else
-      widget_base_->ShowVirtualKeyboard();
-  }
-#endif
-}
-
-void WebFrameWidgetBase::SetHasPointerRawUpdateEventHandlers(
-    bool has_handlers) {
-  widget_base_->widget_input_handler_manager()
-      ->input_event_queue()
-      ->HasPointerRawUpdateEventHandlers(has_handlers);
-}
-
-void WebFrameWidgetBase::SetNeedsLowLatencyInput(bool needs_low_latency) {
-  widget_base_->widget_input_handler_manager()
-      ->input_event_queue()
-      ->SetNeedsLowLatency(needs_low_latency);
-}
-
-void WebFrameWidgetBase::RequestUnbufferedInputEvents() {
-  widget_base_->widget_input_handler_manager()
-      ->input_event_queue()
-      ->RequestUnbufferedInputEvents();
-}
-
-void WebFrameWidgetBase::SetNeedsUnbufferedInputForDebugger(bool unbuffered) {
-  widget_base_->widget_input_handler_manager()
-      ->input_event_queue()
-      ->SetNeedsUnbufferedInputForDebugger(unbuffered);
-}
-
-void WebFrameWidgetBase::DidNavigate() {
-  // The input handler wants to know about navigation so that it can
-  // suppress input until the newly navigated page has a committed frame.
-  // It also resets the state for UMA reporting of input arrival with respect
-  // to document lifecycle.
-  if (!widget_base_->widget_input_handler_manager())
-    return;
-  widget_base_->widget_input_handler_manager()->DidNavigate();
-}
-
-void WebFrameWidgetBase::SetMouseCapture(bool capture) {
-  if (mojom::blink::WidgetInputHandlerHost* host =
-          widget_base_->widget_input_handler_manager()
-              ->GetWidgetInputHandlerHost()) {
-    host->SetMouseCapture(capture);
-  }
-}
-
-gfx::Range WebFrameWidgetBase::CompositionRange() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame || ShouldDispatchImeEventsToPlugin())
-    return gfx::Range::InvalidRange();
-
-  blink::WebInputMethodController* controller =
-      focused_frame->GetInputMethodController();
-  WebRange web_range = controller->CompositionRange();
-  if (web_range.IsNull())
-    return gfx::Range::InvalidRange();
-  return gfx::Range(web_range.StartOffset(), web_range.EndOffset());
-}
-
-void WebFrameWidgetBase::GetCompositionCharacterBoundsInWindow(
-    Vector<gfx::Rect>* bounds_in_dips) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame || ShouldDispatchImeEventsToPlugin())
-    return;
-  blink::WebInputMethodController* controller =
-      focused_frame->GetInputMethodController();
-  blink::WebVector<blink::WebRect> bounds_from_blink;
-  if (!controller->GetCompositionCharacterBounds(bounds_from_blink))
-    return;
-
-  for (auto& rect : bounds_from_blink) {
-    bounds_in_dips->push_back(
-        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(rect)));
-  }
-}
-
-void WebFrameWidgetBase::AddImeTextSpansToExistingText(
-    uint32_t start,
-    uint32_t end,
-    const Vector<ui::ImeTextSpan>& ime_text_spans) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->AddImeTextSpansToExistingText(ime_text_spans, start, end);
-}
-
-Vector<ui::mojom::blink::ImeTextSpanInfoPtr>
-WebFrameWidgetBase::GetImeTextSpansInfo(
-    const WebVector<ui::ImeTextSpan>& ime_text_spans) {
-  auto* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return Vector<ui::mojom::blink::ImeTextSpanInfoPtr>();
-
-  Vector<ui::mojom::blink::ImeTextSpanInfoPtr> ime_text_spans_info;
-
-  for (const auto& ime_text_span : ime_text_spans) {
-    WebRect webrect;
-    unsigned length = ime_text_span.end_offset - ime_text_span.start_offset;
-    focused_frame->FirstRectForCharacterRange(ime_text_span.start_offset,
-                                              length, webrect);
-
-    ime_text_spans_info.push_back(ui::mojom::blink::ImeTextSpanInfo::New(
-        ime_text_span,
-        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(webrect))));
-  }
-  return ime_text_spans_info;
-}
-
-void WebFrameWidgetBase::ClearImeTextSpansByType(uint32_t start,
-                                                 uint32_t end,
-                                                 ui::ImeTextSpan::Type type) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ClearImeTextSpansByType(type, start, end);
-}
-
-void WebFrameWidgetBase::SetCompositionFromExistingText(
-    int32_t start,
-    int32_t end,
-    const Vector<ui::ImeTextSpan>& ime_text_spans) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->SetCompositionFromExistingText(start, end, ime_text_spans);
-}
-
-void WebFrameWidgetBase::ExtendSelectionAndDelete(int32_t before,
-                                                  int32_t after) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExtendSelectionAndDelete(before, after);
-}
-
-void WebFrameWidgetBase::DeleteSurroundingText(int32_t before, int32_t after) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->DeleteSurroundingText(before, after);
-}
-
-void WebFrameWidgetBase::DeleteSurroundingTextInCodePoints(int32_t before,
-                                                           int32_t after) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->DeleteSurroundingTextInCodePoints(before, after);
-}
-
-void WebFrameWidgetBase::SetEditableSelectionOffsets(int32_t start,
-                                                     int32_t end) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->SetEditableSelectionOffsets(start, end);
-}
-
-void WebFrameWidgetBase::ExecuteEditCommand(const String& command,
-                                            const String& value) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(command, value);
-}
-
-void WebFrameWidgetBase::Undo() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Undo"));
-}
-
-void WebFrameWidgetBase::Redo() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Redo"));
-}
-
-void WebFrameWidgetBase::Cut() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Cut"));
-}
-
-void WebFrameWidgetBase::Copy() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Copy"));
-}
-
-void WebFrameWidgetBase::CopyToFindPboard() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  To<WebLocalFrameImpl>(focused_frame)->CopyToFindPboard();
-}
-
-void WebFrameWidgetBase::Paste() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Paste"));
-}
-
-void WebFrameWidgetBase::PasteAndMatchStyle() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("PasteAndMatchStyle"));
-}
-
-void WebFrameWidgetBase::Delete() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("Delete"));
-}
-
-void WebFrameWidgetBase::SelectAll() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->ExecuteCommand(WebString::FromLatin1("SelectAll"));
-}
-
-void WebFrameWidgetBase::CollapseSelection() {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  const blink::WebRange& range =
-      focused_frame->GetInputMethodController()->GetSelectionOffsets();
-  if (range.IsNull())
-    return;
-
-  focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0),
-                             blink::WebLocalFrame::kHideSelectionHandle,
-                             mojom::blink::SelectionMenuBehavior::kHide);
-}
-
-void WebFrameWidgetBase::Replace(const String& word) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  if (!focused_frame->HasSelection())
-    focused_frame->SelectWordAroundCaret();
-  focused_frame->ReplaceSelection(word);
-  focused_frame->Client()->SyncSelectionIfRequired();
-}
-
-void WebFrameWidgetBase::ReplaceMisspelling(const String& word) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  if (!focused_frame->HasSelection())
-    return;
-  focused_frame->ReplaceMisspelledRange(word);
-}
-
-void WebFrameWidgetBase::SelectRange(const gfx::Point& base_in_dips,
-                                     const gfx::Point& extent_in_dips) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->SelectRange(
-      widget_base_->DIPsToRoundedBlinkSpace(base_in_dips),
-      widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
-}
-
-void WebFrameWidgetBase::AdjustSelectionByCharacterOffset(
-    int32_t start,
-    int32_t end,
-    mojom::blink::SelectionMenuBehavior selection_menu_behavior) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  blink::WebRange range =
-      focused_frame->GetInputMethodController()->GetSelectionOffsets();
-  if (range.IsNull())
-    return;
-
-  // Sanity checks to disallow empty and out of range selections.
-  if (start - end > range.length() || range.StartOffset() + start < 0)
-    return;
-
-  // A negative adjust amount moves the selection towards the beginning of
-  // the document, a positive amount moves the selection towards the end of
-  // the document.
-  focused_frame->SelectRange(blink::WebRange(range.StartOffset() + start,
-                                             range.length() + end - start),
-                             blink::WebLocalFrame::kPreserveHandleVisibility,
-                             selection_menu_behavior);
-}
-
-void WebFrameWidgetBase::MoveRangeSelectionExtent(
-    const gfx::Point& extent_in_dips) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->MoveRangeSelectionExtent(
-      widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
-}
-
-void WebFrameWidgetBase::ScrollFocusedEditableNodeIntoRect(
-    const gfx::Rect& rect_in_dips) {
-  WebLocalFrame* local_frame = FocusedWebLocalFrameInWidget();
-  if (!local_frame)
-    return;
-
-  // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
-  // on OOPIFs. Since we are starting a new scroll operation now, call
-  // DidChangeVisibleViewport to ensure that we don't assume the element
-  // is already in view and ignore the scroll.
-  local_frame->Client()->ResetHasScrolledFocusedEditableIntoView();
-  local_frame->Client()->ScrollFocusedEditableElementIntoRect(rect_in_dips);
-}
-
-void WebFrameWidgetBase::ZoomToFindInPageRect(
-    const WebRect& rect_in_root_frame) {
-  if (ForMainFrame()) {
-    View()->ZoomToFindInPageRect(rect_in_root_frame);
-  } else {
-    GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
-        gfx::Rect(rect_in_root_frame));
-  }
-}
-
-void WebFrameWidgetBase::MoveCaret(const gfx::Point& point_in_dips) {
-  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame)
-    return;
-  focused_frame->MoveCaretSelection(
-      widget_base_->DIPsToRoundedBlinkSpace(point_in_dips));
-}
-
-#if defined(OS_ANDROID)
-void WebFrameWidgetBase::SelectWordAroundCaret(
-    SelectWordAroundCaretCallback callback) {
-  auto* focused_frame = FocusedWebLocalFrameInWidget();
-  if (!focused_frame) {
-    std::move(callback).Run(false, 0, 0);
-    return;
-  }
-
-  bool did_select = false;
-  int start_adjust = 0;
-  int end_adjust = 0;
-  blink::WebRange initial_range = focused_frame->SelectionRange();
-  SetHandlingInputEvent(true);
-  if (!initial_range.IsNull())
-    did_select = focused_frame->SelectWordAroundCaret();
-  if (did_select) {
-    blink::WebRange adjusted_range = focused_frame->SelectionRange();
-    DCHECK(!adjusted_range.IsNull());
-    start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset();
-    end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
-  }
-  SetHandlingInputEvent(false);
-  std::move(callback).Run(did_select, start_adjust, end_adjust);
-}
-#endif
-
-void WebFrameWidgetBase::ForEachRemoteFrameControlledByWidget(
-    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
-  ForEachRemoteFrameChildrenControlledByWidget(local_root_->GetFrame(),
-                                               callback);
-}
-
-void WebFrameWidgetBase::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
-                                                  gfx::Rect& focus_root_frame) {
-  const LocalFrame* local_frame = FocusedLocalFrameInWidget();
-  if (!local_frame)
-    return;
-
-  IntRect anchor;
-  IntRect focus;
-  if (!local_frame->Selection().ComputeAbsoluteBounds(anchor, focus))
-    return;
-
-  // Apply the visual viewport for main frames this will apply the page scale.
-  // For subframes it will just be a 1:1 transformation and the browser
-  // will then apply later transformations to these rects.
-  VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
-  anchor_root_frame = visual_viewport.RootFrameToViewport(
-      local_frame->View()->ConvertToRootFrame(anchor));
-  focus_root_frame = visual_viewport.RootFrameToViewport(
-      local_frame->View()->ConvertToRootFrame(focus));
-}
-
-void WebFrameWidgetBase::BatterySavingsChanged(WebBatterySavingsFlags savings) {
-  widget_base_->LayerTreeHost()->SetEnableFrameRateThrottling(
-      savings & kAllowReducedFrameRate);
-}
-
-const viz::LocalSurfaceId& WebFrameWidgetBase::LocalSurfaceIdFromParent() {
-  return widget_base_->local_surface_id_from_parent();
-}
-
-cc::LayerTreeHost* WebFrameWidgetBase::LayerTreeHost() {
-  return widget_base_->LayerTreeHost();
-}
-
-ScreenMetricsEmulator* WebFrameWidgetBase::DeviceEmulator() {
-  return device_emulator_;
-}
-
-bool WebFrameWidgetBase::AutoResizeMode() {
-  return View()->AutoResizeMode();
-}
-
-void WebFrameWidgetBase::SetScreenMetricsEmulationParameters(
-    bool enabled,
-    const DeviceEmulationParams& params) {
-  if (enabled)
-    View()->ActivateDevToolsTransform(params);
-  else
-    View()->DeactivateDevToolsTransform();
-}
-
-void WebFrameWidgetBase::SetScreenInfoAndSize(
-    const ScreenInfo& screen_info,
-    const gfx::Size& widget_size_in_dips,
-    const gfx::Size& visible_viewport_size_in_dips) {
-  // Emulation happens on regular main frames which don't use auto-resize mode.
-  DCHECK(!AutoResizeMode());
-
-  UpdateScreenInfo(screen_info);
-  widget_base_->SetVisibleViewportSizeInDIPs(visible_viewport_size_in_dips);
-  Resize(widget_base_->DIPsToCeiledBlinkSpace(widget_size_in_dips));
-}
-
-void WebFrameWidgetBase::NotifyPageScaleFactorChanged(
-    float page_scale_factor,
-    bool is_pinch_gesture_active) {
-  // Store the value to give to any new RemoteFrame that will be created as a
-  // descendant of this widget.
-  page_scale_factor_in_mainframe_ = page_scale_factor;
-  is_pinch_gesture_active_in_mainframe_ = is_pinch_gesture_active;
-  // Push the page scale factor down to any child RemoteFrames.
-  // TODO(danakj): This ends up setting the page scale factor in the
-  // RenderWidgetHost of the child WebFrameWidgetBase, so that it can bounce
-  // the value down to its WebFrameWidgetBase. Since this is essentially a
-  // global value per-page, we could instead store it once in the browser
-  // (such as in RenderViewHost) and distribute it to each WebFrameWidgetBase
-  // from there.
-  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-      [](float page_scale_factor, bool is_pinch_gesture_active,
-         RemoteFrame* remote_frame) {
-        remote_frame->Client()->PageScaleFactorChanged(page_scale_factor,
-                                                       is_pinch_gesture_active);
-      },
-      page_scale_factor, is_pinch_gesture_active));
-}
-
-void WebFrameWidgetBase::SetPageScaleStateAndLimits(
-    float page_scale_factor,
-    bool is_pinch_gesture_active,
-    float minimum,
-    float maximum) {
-  widget_base_->LayerTreeHost()->SetPageScaleFactorAndLimits(page_scale_factor,
-                                                             minimum, maximum);
-
-  // Only propagate page scale from the main frame.
-  if (ForMainFrame()) {
-    // If page scale hasn't changed, then just return without notifying
-    // the remote frames.
-    if (page_scale_factor == page_scale_factor_in_mainframe_ &&
-        is_pinch_gesture_active == is_pinch_gesture_active_in_mainframe_) {
-      return;
-    }
-
-    NotifyPageScaleFactorChanged(page_scale_factor, is_pinch_gesture_active);
-  }
-}
-
-bool WebFrameWidgetBase::UpdateScreenRects(
-    const gfx::Rect& widget_screen_rect,
-    const gfx::Rect& window_screen_rect) {
-  if (!device_emulator_)
-    return false;
-  device_emulator_->OnUpdateScreenRects(widget_screen_rect, window_screen_rect);
-  return true;
-}
-
-void WebFrameWidgetBase::OrientationChanged() {
-  local_root_->SendOrientationChangeEvent();
-}
-
-void WebFrameWidgetBase::DidUpdateSurfaceAndScreen(
-    const ScreenInfo& previous_original_screen_info) {
-  ScreenInfo screen_info = widget_base_->GetScreenInfo();
-  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
-    View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
-  } else {
-    View()->SetDeviceScaleFactor(screen_info.device_scale_factor);
-  }
-
-  if (Client()->ShouldAutoDetermineCompositingToLCDTextSetting()) {
-    // This causes compositing state to be modified which dirties the
-    // document lifecycle. Android Webview relies on the document
-    // lifecycle being clean after the RenderWidget is initialized, in
-    // order to send IPCs that query and change compositing state. So
-    // WebFrameWidgetBase::Resize() must come after this call, as it runs the
-    // entire document lifecycle.
-    View()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
-        widget_base_->ComputePreferCompositingToLCDText());
-  }
-
-  // When the device scale changes, the size and position of the popup would
-  // need to be adjusted, which we can't do. Just close the popup, which is
-  // also consistent with page zoom and resize behavior.
-  if (previous_original_screen_info.device_scale_factor !=
-      screen_info.device_scale_factor) {
-    View()->CancelPagePopup();
-  }
-
-  // Propagate changes down to child local root RenderWidgets and BrowserPlugins
-  // in other frame trees/processes.
-  ScreenInfo original_screen_info = GetOriginalScreenInfo();
-  if (previous_original_screen_info != original_screen_info) {
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const ScreenInfo& original_screen_info, RemoteFrame* remote_frame) {
-          remote_frame->Client()->DidChangeScreenInfo(original_screen_info);
-        },
-        original_screen_info));
-  }
-}
-
-gfx::Rect WebFrameWidgetBase::ViewportVisibleRect() {
-  if (ForMainFrame()) {
-    return widget_base_->CompositorViewportRect();
-  } else {
-    return child_data().compositor_visible_rect;
-  }
-}
-
-const ScreenInfo& WebFrameWidgetBase::GetOriginalScreenInfo() {
-  if (device_emulator_)
-    return device_emulator_->original_screen_info();
-  return widget_base_->GetScreenInfo();
-}
-
-base::Optional<blink::mojom::ScreenOrientation>
-WebFrameWidgetBase::ScreenOrientationOverride() {
-  return View()->ScreenOrientationOverride();
-}
-
-void WebFrameWidgetBase::WasHidden() {
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrame* local_frame) {
-        local_frame->Client()->WasHidden();
-      }));
-}
-
-void WebFrameWidgetBase::WasShown(bool was_evicted) {
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrame* local_frame) {
-        local_frame->Client()->WasShown();
-      }));
-  if (was_evicted) {
-    ForEachRemoteFrameControlledByWidget(
-        WTF::BindRepeating([](RemoteFrame* remote_frame) {
-          remote_frame->Client()->WasEvicted();
-        }));
-  }
-}
-
-void WebFrameWidgetBase::RunPaintBenchmark(int repeat_count,
-                                           cc::PaintBenchmarkResult& result) {
-  if (!ForMainFrame())
-    return;
-  if (auto* frame_view = LocalRootImpl()->GetFrameView())
-    frame_view->RunPaintBenchmark(repeat_count, result);
-}
-
-void WebFrameWidgetBase::NotifyInputObservers(
-    const WebCoalescedInputEvent& coalesced_event) {
-  LocalFrame* frame = FocusedLocalFrameInWidget();
-  if (!frame)
-    return;
-
-  LocalFrameView* frame_view = frame->View();
-  if (!frame_view)
-    return;
-
-  const WebInputEvent& input_event = coalesced_event.Event();
-  auto& paint_timing_detector = frame_view->GetPaintTimingDetector();
-
-  if (paint_timing_detector.NeedToNotifyInputOrScroll())
-    paint_timing_detector.NotifyInputEvent(input_event.GetType());
-}
-
-Frame* WebFrameWidgetBase::FocusedCoreFrame() const {
-  return GetPage() ? GetPage()->GetFocusController().FocusedOrMainFrame()
-                   : nullptr;
-}
-
-Element* WebFrameWidgetBase::FocusedElement() const {
-  LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
-  if (!frame)
-    return nullptr;
-
-  Document* document = frame->GetDocument();
-  if (!document)
-    return nullptr;
-
-  return document->FocusedElement();
-}
-
-HitTestResult WebFrameWidgetBase::HitTestResultForRootFramePos(
-    const FloatPoint& pos_in_root_frame) {
-  FloatPoint doc_point =
-      LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
-          pos_in_root_frame);
-  HitTestLocation location(doc_point);
-  HitTestResult result =
-      LocalRootImpl()->GetFrame()->View()->HitTestWithThrottlingAllowed(
-          location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
-  result.SetToShadowHostIfInRestrictedShadowRoot();
-  return result;
-}
-
-bool WebFrameWidgetBase::SynchronousResizeModeForTestingEnabled() {
-  return main_data().synchronous_resize_mode_for_testing;
-}
-
-KURL WebFrameWidgetBase::GetURLForDebugTrace() {
-  WebFrame* main_frame = View()->MainFrame();
-  if (main_frame->IsWebLocalFrame())
-    return main_frame->ToWebLocalFrame()->GetDocument().Url();
-  return {};
-}
-
-float WebFrameWidgetBase::GetTestingDeviceScaleFactorOverride() {
-  return device_scale_factor_for_testing_;
-}
-
-void WebFrameWidgetBase::ReleaseMouseLockAndPointerCaptureForTesting() {
-  GetPage()->GetPointerLockController().ExitPointerLock();
-  MouseCaptureLost();
-}
-
-const viz::FrameSinkId& WebFrameWidgetBase::GetFrameSinkId() {
-  // It is valid to create a WebFrameWidget with an invalid frame sink id for
-  // printing and placeholders. But if we go to use it, it should be valid.
-  DCHECK(frame_sink_id_.is_valid());
-  return frame_sink_id_;
-}
-
-WebHitTestResult WebFrameWidgetBase::HitTestResultAt(const gfx::PointF& point) {
-  return CoreHitTestResultAt(point);
-}
-
-void WebFrameWidgetBase::SetZoomLevelForTesting(double zoom_level) {
-  DCHECK(ForMainFrame());
-  DCHECK_NE(zoom_level, -INFINITY);
-  zoom_level_for_testing_ = zoom_level;
-  SetZoomLevel(zoom_level);
-}
-
-void WebFrameWidgetBase::ResetZoomLevelForTesting() {
-  DCHECK(ForMainFrame());
-  zoom_level_for_testing_ = -INFINITY;
-  SetZoomLevel(0);
-}
-
-void WebFrameWidgetBase::SetDeviceScaleFactorForTesting(float factor) {
-  DCHECK(ForMainFrame());
-  DCHECK_GE(factor, 0.f);
-
-  // Stash the window size before we adjust the scale factor, as subsequent
-  // calls to convert will use the new scale factor.
-  gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
-  device_scale_factor_for_testing_ = factor;
-
-  // Receiving a 0 is used to reset between tests, it removes the override in
-  // order to listen to the browser for the next test.
-  if (!factor)
-    return;
-
-  // We are changing the device scale factor from the renderer, so allocate a
-  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
-
-  ScreenInfo info = widget_base_->GetScreenInfo();
-  info.device_scale_factor = factor;
-  gfx::Size size_with_dsf = gfx::ScaleToCeiledSize(size_in_dips, factor);
-  widget_base_->UpdateCompositorViewportAndScreenInfo(gfx::Rect(size_with_dsf),
-                                                      info);
-  if (!AutoResizeMode()) {
-    // This picks up the new device scale factor as
-    // `UpdateCompositorViewportAndScreenInfo()` has applied a new value.
-    Resize(widget_base_->DIPsToCeiledBlinkSpace(size_in_dips));
-  }
-}
-
-WebPlugin* WebFrameWidgetBase::GetFocusedPluginContainer() {
-  LocalFrame* focused_frame = FocusedLocalFrameInWidget();
-  if (!focused_frame)
-    return nullptr;
-  if (auto* container = focused_frame->GetWebPluginContainer())
-    return container->Plugin();
-  return nullptr;
-}
-
-bool WebFrameWidgetBase::CanComposeInline() {
-  if (auto* plugin = GetFocusedPluginContainer())
-    return plugin->CanComposeInline();
-  return true;
-}
-
-bool WebFrameWidgetBase::ShouldDispatchImeEventsToPlugin() {
-  if (auto* plugin = GetFocusedPluginContainer())
-    return plugin->ShouldDispatchImeEventsToPlugin();
-  return false;
-}
-
-void WebFrameWidgetBase::ImeSetCompositionForPlugin(
-    const String& text,
-    const Vector<ui::ImeTextSpan>& ime_text_spans,
-    const gfx::Range& replacement_range,
-    int selection_start,
-    int selection_end) {
-  if (auto* plugin = GetFocusedPluginContainer()) {
-    plugin->ImeSetCompositionForPlugin(
-        text,
-        std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
-                                     ime_text_spans.end()),
-        replacement_range, selection_start, selection_end);
-  }
-}
-
-void WebFrameWidgetBase::ImeCommitTextForPlugin(
-    const String& text,
-    const Vector<ui::ImeTextSpan>& ime_text_spans,
-    const gfx::Range& replacement_range,
-    int relative_cursor_pos) {
-  if (auto* plugin = GetFocusedPluginContainer()) {
-    plugin->ImeCommitTextForPlugin(
-        text,
-        std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
-                                     ime_text_spans.end()),
-        replacement_range, relative_cursor_pos);
-  }
-}
-
-void WebFrameWidgetBase::ImeFinishComposingTextForPlugin(bool keep_selection) {
-  if (auto* plugin = GetFocusedPluginContainer())
-    plugin->ImeFinishComposingTextForPlugin(keep_selection);
-}
-
-void WebFrameWidgetBase::SetWindowRect(const gfx::Rect& window_rect) {
-  DCHECK(ForMainFrame());
-  if (SynchronousResizeModeForTestingEnabled()) {
-    // This is a web-test-only path. At one point, it was planned to be
-    // removed. See https://crbug.com/309760.
-    SetWindowRectSynchronously(window_rect);
-    return;
-  }
-
-  SetPendingWindowRect(window_rect);
-  View()->SendWindowRectToMainFrameHost(
-      window_rect, WTF::Bind(&WebFrameWidgetBase::AckPendingWindowRect,
-                             WrapWeakPersistent(this)));
-}
-
-void WebFrameWidgetBase::SetWindowRectSynchronouslyForTesting(
-    const gfx::Rect& new_window_rect) {
-  DCHECK(ForMainFrame());
-  SetWindowRectSynchronously(new_window_rect);
-}
-
-void WebFrameWidgetBase::SetWindowRectSynchronously(
-    const gfx::Rect& new_window_rect) {
-  // This method is only call in tests, and it applies the |new_window_rect| to
-  // all three of:
-  // a) widget size (in |size_|)
-  // b) blink viewport (in |visible_viewport_size_|)
-  // c) compositor viewport (in cc::LayerTreeHost)
-  // Normally the browser controls these three things independently, but this is
-  // used in tests to control the size from the renderer.
-
-  // We are resizing the window from the renderer, so allocate a new
-  // viz::LocalSurfaceId to avoid surface invariants violations in tests.
-  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
-
-  gfx::Rect compositor_viewport_pixel_rect(gfx::ScaleToCeiledSize(
-      new_window_rect.size(),
-      widget_base_->GetScreenInfo().device_scale_factor));
-  widget_base_->UpdateSurfaceAndScreenInfo(
-      widget_base_->local_surface_id_from_parent(),
-      compositor_viewport_pixel_rect, widget_base_->GetScreenInfo());
-
-  Resize(new_window_rect.size());
-  widget_base_->SetScreenRects(new_window_rect, new_window_rect);
-}
-
-void WebFrameWidgetBase::DidCreateLocalRootView() {
-  // If this WebWidget still hasn't received its size from the embedder, block
-  // the parser. This is necessary, because the parser can cause layout to
-  // happen, which needs to be done with the correct size.
-  if (ForSubframe() && !size_) {
-    child_data().did_suspend_parsing = true;
-    LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->BlockParser();
-  }
-}
-
-mojom::blink::ScrollIntoViewParamsPtr
-WebFrameWidgetBase::GetScrollParamsForFocusedEditableElement(
-    const Element& element,
-    PhysicalRect& out_rect_to_scroll) {
-  // For main frames, scrolling takes place in two phases.
-  if (ForMainFrame()) {
-    // Since the page has been resized, the layout may have changed. The page
-    // scale animation started by ZoomAndScrollToFocusedEditableRect will scroll
-    // only the visual and layout viewports. We'll call ScrollRectToVisible with
-    // the stop_at_main_frame_layout_viewport param to ensure the element is
-    // actually visible in the page.
-    mojom::blink::ScrollIntoViewParamsPtr params =
-        ScrollAlignment::CreateScrollIntoViewParams(
-            ScrollAlignment::CenterIfNeeded(),
-            ScrollAlignment::CenterIfNeeded(),
-            mojom::blink::ScrollType::kProgrammatic, false,
-            mojom::blink::ScrollBehavior::kInstant);
-    params->stop_at_main_frame_layout_viewport = true;
-    out_rect_to_scroll =
-        PhysicalRect(element.GetLayoutObject()->AbsoluteBoundingBoxRect());
-    return params;
-  }
-
-  LocalFrameView& frame_view = *element.GetDocument().View();
-  IntRect absolute_element_bounds =
-      element.GetLayoutObject()->AbsoluteBoundingBoxRect();
-  IntRect absolute_caret_bounds =
-      element.GetDocument().GetFrame()->Selection().AbsoluteCaretBounds();
-  // Ideally, the chosen rectangle includes the element box and caret bounds
-  // plus some margin on the left. If this does not work (i.e., does not fit
-  // inside the frame view), then choose a subrect which includes the caret
-  // bounds. It is preferable to also include element bounds' location and left
-  // align the scroll. If this cant be satisfied, the scroll will be right
-  // aligned.
-  IntRect maximal_rect =
-      UnionRect(absolute_element_bounds, absolute_caret_bounds);
-
-  // Set the ideal margin.
-  maximal_rect.ShiftXEdgeTo(
-      maximal_rect.X() -
-      static_cast<int>(kIdealPaddingRatio * absolute_element_bounds.Width()));
-
-  bool maximal_rect_fits_in_frame =
-      !(frame_view.Size() - maximal_rect.Size()).IsEmpty();
-
-  if (!maximal_rect_fits_in_frame) {
-    IntRect frame_rect(maximal_rect.Location(), frame_view.Size());
-    maximal_rect.Intersect(frame_rect);
-    IntPoint point_forced_to_be_visible =
-        absolute_caret_bounds.MaxXMaxYCorner() +
-        IntSize(kCaretPadding, kCaretPadding);
-    if (!maximal_rect.Contains(point_forced_to_be_visible)) {
-      // Move the rect towards the point until the point is barely contained.
-      maximal_rect.Move(point_forced_to_be_visible -
-                        maximal_rect.MaxXMaxYCorner());
-    }
-  }
-
-  mojom::blink::ScrollIntoViewParamsPtr params =
-      ScrollAlignment::CreateScrollIntoViewParams();
-  params->zoom_into_rect = View()->ShouldZoomToLegibleScale(element);
-  params->relative_element_bounds = NormalizeRect(
-      Intersection(absolute_element_bounds, maximal_rect), maximal_rect);
-  params->relative_caret_bounds = NormalizeRect(
-      Intersection(absolute_caret_bounds, maximal_rect), maximal_rect);
-  params->behavior = mojom::blink::ScrollBehavior::kInstant;
-  out_rect_to_scroll = PhysicalRect(maximal_rect);
-  return params;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
deleted file mode 100644
index 9b6da2f9..0000000
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ /dev/null
@@ -1,978 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_BASE_H_
-
-#include "base/single_thread_task_runner.h"
-#include "build/build_config.h"
-#include "cc/input/event_listener_properties.h"
-#include "cc/input/layer_selection_bound.h"
-#include "cc/input/overscroll_behavior.h"
-#include "cc/trees/layer_tree_host.h"
-#include "services/viz/public/mojom/hit_test/input_target_client.mojom-blink.h"
-#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
-#include "third_party/blink/public/common/input/web_gesture_device.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h"
-#include "third_party/blink/public/mojom/page/drag.mojom-blink.h"
-#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
-#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
-#include "third_party/blink/public/platform/web_battery_savings.h"
-#include "third_party/blink/public/platform/web_drag_data.h"
-#include "third_party/blink/public/web/web_frame_widget.h"
-#include "third_party/blink/public/web/web_meaningful_layout.h"
-#include "third_party/blink/renderer/core/clipboard/data_object.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
-#include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
-#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
-#include "third_party/blink/renderer/platform/graphics/apply_viewport_changes.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
-#include "third_party/blink/renderer/platform/text/text_direction.h"
-#include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/widget/frame_widget.h"
-#include "third_party/blink/renderer/platform/widget/widget_base_client.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-#include "ui/base/mojom/ui_base_types.mojom-shared.h"
-
-namespace gfx {
-class Point;
-class PointF;
-}  // namespace gfx
-
-namespace blink {
-class AnimationWorkletMutatorDispatcherImpl;
-class FloatPoint;
-class HitTestResult;
-class HTMLPlugInElement;
-class Page;
-class PageWidgetEventHandler;
-class PaintWorkletPaintDispatcher;
-class RemoteFrame;
-class WebLocalFrameImpl;
-class WebPlugin;
-class WebViewImpl;
-class WidgetBase;
-class ScreenMetricsEmulator;
-
-class CORE_EXPORT WebFrameWidgetBase
-    : public GarbageCollected<WebFrameWidgetBase>,
-      public WebFrameWidget,
-      public WidgetBaseClient,
-      public mojom::blink::FrameWidget,
-      public viz::mojom::blink::InputTargetClient,
-      public FrameWidget,
-      public PageWidgetEventHandler {
- public:
-  WebFrameWidgetBase(
-      WebWidgetClient&,
-      CrossVariantMojoAssociatedRemote<
-          mojom::blink::FrameWidgetHostInterfaceBase> frame_widget_host,
-      CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
-          frame_widget,
-      CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
-          widget_host,
-      CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
-          widget,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      const viz::FrameSinkId& frame_sink_id,
-      bool hidden,
-      bool never_composited,
-      bool is_for_child_local_root,
-      bool is_for_nested_main_frame);
-  ~WebFrameWidgetBase() override;
-
-  // Returns the WebFrame that this widget is attached to. It will be a local
-  // root since only local roots have a widget attached.
-  WebLocalFrameImpl* LocalRootImpl() const { return local_root_; }
-
-  // Returns the bounding box of the block type node touched by the WebPoint.
-  WebRect ComputeBlockBound(const gfx::Point& point_in_root_frame,
-                            bool ignore_clipping) const;
-
-  void BindLocalRoot(WebLocalFrame&);
-
-  // If this widget is for the top most main frame. This is different than
-  // |ForMainFrame| because |ForMainFrame| could return true but this method
-  // returns false. If this widget is a MainFrame widget embedded in another
-  // widget, for example embedding a portal.
-  bool ForTopMostMainFrame() const;
-
-  // Adjusts whether the widget is nested or not. This is called during portal
-  // transitions.
-  void SetIsNestedMainFrameWidget(bool is_nested);
-
-  // Returns true if this widget is for a local root that is a child frame,
-  // false otherwise.
-  bool ForSubframe() const { return is_for_child_local_root_; }
-
-  // Opposite of |ForSubframe|. If this widget is for the local main frame.
-  bool ForMainFrame() const { return !ForSubframe(); }
-
-  // Called when the intrinsic size of the owning container is changing its
-  // size. This should only be called when `ForSubframe` is true.
-  void IntrinsicSizingInfoChanged(mojom::blink::IntrinsicSizingInfoPtr);
-
-  void AutoscrollStart(const gfx::PointF& position);
-  void AutoscrollFling(const gfx::Vector2dF& position);
-  void AutoscrollEnd();
-
-  // Notifies RenderWidgetHostImpl that the frame widget has painted something.
-  void DidMeaningfulLayout(WebMeaningfulLayout layout_type);
-
-  bool HandleCurrentKeyboardEvent();
-
-  // Creates or returns cached mutator dispatcher. This usually requires a
-  // round trip to the compositor. The returned WeakPtr must only be
-  // dereferenced on the output |mutator_task_runner|.
-  base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
-  EnsureCompositorMutatorDispatcher(
-      scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner);
-
-  // TODO: consider merge the input and return value to be one parameter.
-  // Creates or returns cached paint dispatcher. The returned WeakPtr must only
-  // be dereferenced on the output |paint_task_runner|.
-  base::WeakPtr<PaintWorkletPaintDispatcher> EnsureCompositorPaintDispatcher(
-      scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner);
-
-  HitTestResult CoreHitTestResultAt(const gfx::PointF&);
-
-  // FrameWidget implementation.
-  WebWidgetClient* Client() const final { return client_; }
-  cc::AnimationHost* AnimationHost() const final;
-  void SetOverscrollBehavior(
-      const cc::OverscrollBehavior& overscroll_behavior) final;
-  void RequestAnimationAfterDelay(const base::TimeDelta&) final;
-  void SetRootLayer(scoped_refptr<cc::Layer>) override;
-  void RegisterSelection(cc::LayerSelection selection) final;
-  void RequestDecode(const cc::PaintImage&,
-                     base::OnceCallback<void(bool)>) final;
-  void NotifySwapAndPresentationTimeInBlink(
-      WebReportTimeCallback swap_callback,
-      WebReportTimeCallback presentation_callback) final;
-  void RequestBeginMainFrameNotExpected(bool request) final;
-  int GetLayerTreeId() final;
-  void SetEventListenerProperties(cc::EventListenerClass,
-                                  cc::EventListenerProperties) final;
-  cc::EventListenerProperties EventListenerProperties(
-      cc::EventListenerClass) const final;
-  mojom::blink::DisplayMode DisplayMode() const override;
-  const WebVector<gfx::Rect>& WindowSegments() const override;
-  void SetDelegatedInkMetadata(
-      std::unique_ptr<viz::DelegatedInkMetadata> metadata) final;
-  void DidOverscroll(const gfx::Vector2dF& overscroll_delta,
-                     const gfx::Vector2dF& accumulated_overscroll,
-                     const gfx::PointF& position,
-                     const gfx::Vector2dF& velocity) override;
-  void InjectGestureScrollEvent(WebGestureDevice device,
-                                const gfx::Vector2dF& delta,
-                                ui::ScrollGranularity granularity,
-                                cc::ElementId scrollable_area_element_id,
-                                WebInputEvent::Type injected_type) override;
-  void DidChangeCursor(const ui::Cursor&) override;
-  void GetCompositionCharacterBoundsInWindow(
-      Vector<gfx::Rect>* bounds_in_dips) override;
-  gfx::Range CompositionRange() override;
-  WebTextInputInfo TextInputInfo() override;
-  ui::mojom::VirtualKeyboardVisibilityRequest
-  GetLastVirtualKeyboardVisibilityRequest() override;
-  bool ShouldSuppressKeyboardForFocusedElement() override;
-  void GetEditContextBoundsInWindow(
-      base::Optional<gfx::Rect>* control_bounds,
-      base::Optional<gfx::Rect>* selection_bounds) override;
-  int32_t ComputeWebTextInputNextPreviousFlags() override;
-  void ResetVirtualKeyboardVisibilityRequest() override;
-  bool GetSelectionBoundsInWindow(gfx::Rect* focus,
-                                  gfx::Rect* anchor,
-                                  base::i18n::TextDirection* focus_dir,
-                                  base::i18n::TextDirection* anchor_dir,
-                                  bool* is_anchor_first) override;
-  void ClearTextInputState() override;
-
-  bool SetComposition(const String& text,
-                      const Vector<ui::ImeTextSpan>& ime_text_spans,
-                      const gfx::Range& replacement_range,
-                      int selection_start,
-                      int selection_end) override;
-  void CommitText(const String& text,
-                  const Vector<ui::ImeTextSpan>& ime_text_spans,
-                  const gfx::Range& replacement_range,
-                  int relative_cursor_pos) override;
-  void FinishComposingText(bool keep_selection) override;
-  bool IsProvisional() override;
-  uint64_t GetScrollableContainerIdAt(
-      const gfx::PointF& point_in_dips) override;
-  bool ShouldHandleImeEvents() override;
-  void SetEditCommandsForNextKeyEvent(
-      Vector<mojom::blink::EditCommandPtr> edit_commands) override;
-
-  void AddImeTextSpansToExistingText(
-      uint32_t start,
-      uint32_t end,
-      const Vector<ui::ImeTextSpan>& ime_text_spans) override;
-  Vector<ui::mojom::blink::ImeTextSpanInfoPtr> GetImeTextSpansInfo(
-      const WebVector<ui::ImeTextSpan>& ime_text_spans) override;
-  void ClearImeTextSpansByType(uint32_t start,
-                               uint32_t end,
-                               ui::ImeTextSpan::Type type) override;
-  void SetCompositionFromExistingText(
-      int32_t start,
-      int32_t end,
-      const Vector<ui::ImeTextSpan>& ime_text_spans) override;
-  void ExtendSelectionAndDelete(int32_t before, int32_t after) override;
-  void DeleteSurroundingText(int32_t before, int32_t after) override;
-  void DeleteSurroundingTextInCodePoints(int32_t before,
-                                         int32_t after) override;
-  void SetEditableSelectionOffsets(int32_t start, int32_t end) override;
-  void ExecuteEditCommand(const String& command, const String& value) override;
-  void Undo() override;
-  void Redo() override;
-  void Cut() override;
-  void Copy() override;
-  void CopyToFindPboard() override;
-  void Paste() override;
-  void PasteAndMatchStyle() override;
-  void Delete() override;
-  void SelectAll() override;
-  void CollapseSelection() override;
-  void Replace(const String& word) override;
-  void ReplaceMisspelling(const String& word) override;
-  void SelectRange(const gfx::Point& base_in_dips,
-                   const gfx::Point& extent_in_dips) override;
-  void AdjustSelectionByCharacterOffset(
-      int32_t start,
-      int32_t end,
-      mojom::blink::SelectionMenuBehavior behavior) override;
-  void MoveRangeSelectionExtent(const gfx::Point& extent_in_dips) override;
-  void ScrollFocusedEditableNodeIntoRect(
-      const gfx::Rect& rect_in_dips) override;
-  void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override;
-  void MoveCaret(const gfx::Point& point_in_dips) override;
-#if defined(OS_ANDROID)
-  void SelectWordAroundCaret(SelectWordAroundCaretCallback callback) override;
-#endif
-  gfx::RectF BlinkSpaceToDIPs(const gfx::RectF& rect) override;
-  gfx::Rect BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) override;
-  gfx::Size BlinkSpaceToFlooredDIPs(const gfx::Size& size) override;
-  gfx::RectF DIPsToBlinkSpace(const gfx::RectF& rect) override;
-  gfx::PointF DIPsToBlinkSpace(const gfx::PointF& point) override;
-  gfx::Point DIPsToRoundedBlinkSpace(const gfx::Point& point) override;
-  float DIPsToBlinkSpace(float scalar) override;
-  void RequestMouseLock(
-      bool has_transient_user_activation,
-      bool request_unadjusted_movement,
-      mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback)
-      override;
-  void MouseCaptureLost() override;
-  bool CanComposeInline() override;
-  bool ShouldDispatchImeEventsToPlugin() override;
-  void ImeSetCompositionForPlugin(const String& text,
-                                  const Vector<ui::ImeTextSpan>& ime_text_spans,
-                                  const gfx::Range& replacement_range,
-                                  int selection_start,
-                                  int selection_end) override;
-  void ImeCommitTextForPlugin(const String& text,
-                              const Vector<ui::ImeTextSpan>& ime_text_spans,
-                              const gfx::Range& replacement_range,
-                              int relative_cursor_pos) override;
-  void ImeFinishComposingTextForPlugin(bool keep_selection) override;
-
-  // WebFrameWidget implementation.
-  WebLocalFrame* LocalRoot() const override;
-  void SendOverscrollEventFromImplSide(
-      const gfx::Vector2dF& overscroll_delta,
-      cc::ElementId scroll_latched_element_id) override;
-  void SendScrollEndEventFromImplSide(
-      cc::ElementId scroll_latched_element_id) override;
-  WebInputMethodController* GetActiveWebInputMethodController() const override;
-  WebLocalFrame* FocusedWebLocalFrameInWidget() const override;
-  bool ScrollFocusedEditableElementIntoView() override;
-  void ApplyViewportChangesForTesting(
-      const ApplyViewportChangesArgs& args) override;
-  void NotifySwapAndPresentationTime(
-      WebReportTimeCallback swap_callback,
-      WebReportTimeCallback presentation_callback) override;
-  scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
-      override;
-  void WaitForDebuggerWhenShown() override;
-  void SetTextZoomFactor(float text_zoom_factor) override;
-  float TextZoomFactor() override;
-  void SetMainFrameOverlayColor(SkColor) override;
-  void AddEditCommandForNextKeyEvent(const WebString& name,
-                                     const WebString& value) override;
-  void ClearEditCommands() override;
-  bool IsPasting() override;
-  bool HandlingSelectRange() override;
-  void ReleaseMouseLockAndPointerCaptureForTesting() override;
-  const viz::FrameSinkId& GetFrameSinkId() override;
-  WebHitTestResult HitTestResultAt(const gfx::PointF&) override;
-  void SetZoomLevelForTesting(double zoom_level) override;
-  void ResetZoomLevelForTesting() override;
-  void SetDeviceScaleFactorForTesting(float factor) override;
-
-  // Called when a drag-n-drop operation should begin.
-  void StartDragging(const WebDragData&,
-                     DragOperationsMask,
-                     const SkBitmap& drag_image,
-                     const gfx::Point& drag_image_offset);
-
-  bool DoingDragAndDrop() { return doing_drag_and_drop_; }
-  static void SetIgnoreInputEvents(bool value) { ignore_input_events_ = value; }
-  static bool IgnoreInputEvents() { return ignore_input_events_; }
-
-  // Resets the layout tracking steps for the main frame. When
-  // `UpdateLifecycle()` is called it generates `WebMeaningfulLayout` events
-  // only once. This resets the state back to the default so it will fire new
-  // events.
-  void ResetMeaningfulLayoutStateForMainFrame();
-
-  // WebWidget methods.
-  cc::LayerTreeHost* InitializeCompositing(
-      scheduler::WebThreadScheduler* main_thread_scheduler,
-      cc::TaskGraphRunner* task_graph_runner,
-      const ScreenInfo& screen_info,
-      std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
-      const cc::LayerTreeSettings* settings) override;
-  void Close(
-      scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) override;
-  void SetCompositorVisible(bool visible) override;
-  gfx::Size Size() override;
-  void Resize(const gfx::Size& size_with_dsf) override;
-  void SetCursor(const ui::Cursor& cursor) override;
-  bool HandlingInputEvent() override;
-  void SetHandlingInputEvent(bool handling) override;
-  void ProcessInputEventSynchronouslyForTesting(const WebCoalescedInputEvent&,
-                                                HandledEventCallback) override;
-  WebInputEventResult DispatchBufferedTouchEvents() override;
-  WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
-  void UpdateTextInputState() override;
-  void UpdateSelectionBounds() override;
-  void ShowVirtualKeyboard() override;
-  bool HasFocus() override;
-  void SetFocus(bool focus) override;
-  void FlushInputProcessedCallback() override;
-  void CancelCompositionForPepper() override;
-  void ApplyVisualProperties(
-      const VisualProperties& visual_properties) override;
-  bool PinchGestureActiveInMainFrame() override;
-  float PageScaleInMainFrame() override;
-  const ScreenInfo& GetScreenInfo() override;
-  gfx::Rect WindowRect() override;
-  gfx::Rect ViewRect() override;
-  void SetScreenRects(const gfx::Rect& widget_screen_rect,
-                      const gfx::Rect& window_screen_rect) override;
-  gfx::Size VisibleViewportSizeInDIPs() override;
-  bool IsHidden() const override;
-  WebString GetLastToolTipTextForTesting() const override;
-  float GetEmulatorScale() override;
-
-  // WidgetBaseClient methods.
-  void BeginMainFrame(base::TimeTicks last_frame_time) override;
-  void BeginCommitCompositorFrame() override;
-  void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
-  void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override;
-  void RecordManipulationTypeCounts(cc::ManipulationInfo info) override;
-  void RecordDispatchRafAlignedInputTime(
-      base::TimeTicks raf_aligned_input_start_time) override;
-  void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override;
-  void RecordStartOfFrameMetrics() override;
-  void RecordEndOfFrameMetrics(
-      base::TimeTicks,
-      cc::ActiveFrameSequenceTrackers trackers) override;
-  std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
-      override;
-  std::unique_ptr<cc::WebVitalMetrics> GetWebVitalMetrics() override;
-  void BeginUpdateLayers() override;
-  void EndUpdateLayers() override;
-  void DidCommitAndDrawCompositorFrame() override;
-  std::unique_ptr<cc::LayerTreeFrameSink> AllocateNewLayerTreeFrameSink()
-      override;
-  void DidObserveFirstScrollDelay(
-      base::TimeDelta first_scroll_delay,
-      base::TimeTicks first_scroll_timestamp) override;
-  void DidBeginMainFrame() override;
-  void UpdateLifecycle(WebLifecycleUpdate requested_update,
-                       DocumentUpdateReason reason) override;
-  void WillBeginMainFrame() override;
-  void DidCompletePageScaleAnimation() override;
-  void FocusChangeComplete() override;
-  bool WillHandleGestureEvent(const WebGestureEvent& event) override;
-  void WillHandleMouseEvent(const WebMouseEvent& event) override;
-  void ObserveGestureEventAndResult(
-      const WebGestureEvent& gesture_event,
-      const gfx::Vector2dF& unused_delta,
-      const cc::OverscrollBehavior& overscroll_behavior,
-      bool event_processed) override;
-  bool SupportsBufferedTouchEvents() override { return true; }
-  void DidHandleKeyEvent() override;
-  WebTextInputType GetTextInputType() override;
-  void SetCursorVisibilityState(bool is_visible) override;
-  blink::FrameWidget* FrameWidget() override { return this; }
-  void ScheduleAnimation() override;
-  void FocusChanged(bool enable) override;
-  bool ShouldAckSyntheticInputImmediately() override;
-  void UpdateVisualProperties(
-      const VisualProperties& visual_properties) override;
-  void ScheduleAnimationForWebTests() override;
-  bool UpdateScreenRects(const gfx::Rect& widget_screen_rect,
-                         const gfx::Rect& window_screen_rect) override;
-  void OrientationChanged() override;
-  void DidUpdateSurfaceAndScreen(
-      const ScreenInfo& previous_original_screen_info) override;
-  gfx::Rect ViewportVisibleRect() override;
-  const ScreenInfo& GetOriginalScreenInfo() override;
-  base::Optional<blink::mojom::ScreenOrientation> ScreenOrientationOverride()
-      override;
-  void WasHidden() override;
-  void WasShown(bool was_evicted) override;
-  void RunPaintBenchmark(int repeat_count,
-                         cc::PaintBenchmarkResult& result) override;
-  KURL GetURLForDebugTrace() override;
-  float GetTestingDeviceScaleFactorOverride() override;
-
-  // mojom::blink::FrameWidget methods.
-  void DragTargetDragEnter(const WebDragData&,
-                           const gfx::PointF& point_in_viewport,
-                           const gfx::PointF& screen_point,
-                           DragOperationsMask operations_allowed,
-                           uint32_t key_modifiers,
-                           DragTargetDragEnterCallback callback) override;
-  void DragTargetDragOver(const gfx::PointF& point_in_viewport,
-                          const gfx::PointF& screen_point,
-                          DragOperationsMask operations_allowed,
-                          uint32_t key_modifiers,
-                          DragTargetDragOverCallback callback) override;
-  void DragTargetDragLeave(const gfx::PointF& point_in_viewport,
-                           const gfx::PointF& screen_point) override;
-  void DragTargetDrop(const WebDragData&,
-                      const gfx::PointF& point_in_viewport,
-                      const gfx::PointF& screen_point,
-                      uint32_t key_modifiers) override;
-  void DragSourceEndedAt(const gfx::PointF& point_in_viewport,
-                         const gfx::PointF& screen_point,
-                         DragOperation) override;
-  void DragSourceSystemDragEnded() override;
-  void SetBackgroundOpaque(bool opaque) override;
-  void SetActive(bool active) override;
-  // For both mainframe and childframe change the text direction of the
-  // currently selected input field (if any).
-  void SetTextDirection(base::i18n::TextDirection direction) override;
-  // Sets the inherited effective touch action on an out-of-process iframe.
-  void SetInheritedEffectiveTouchActionForSubFrame(
-      WebTouchAction touch_action) override;
-  // Toggles render throttling for an out-of-process iframe. Local frames are
-  // throttled based on their visibility in the viewport, but remote frames
-  // have to have throttling information propagated from parent to child
-  // across processes.
-  void UpdateRenderThrottlingStatusForSubFrame(bool is_throttled,
-                                               bool subtree_throttled) override;
-  void ShowContextMenu(ui::mojom::MenuSourceType source_type,
-                       const gfx::Point& location) override;
-  void SetViewportIntersection(
-      mojom::blink::ViewportIntersectionStatePtr intersection_state) override;
-  void EnableDeviceEmulation(const DeviceEmulationParams& parameters) override;
-  void DisableDeviceEmulation() override;
-  // Sets the inert bit on an out-of-process iframe, causing it to ignore
-  // input.
-  void SetIsInertForSubFrame(bool inert) override;
-#if defined(OS_MAC)
-  void GetStringAtPoint(const gfx::Point& point_in_local_root,
-                        GetStringAtPointCallback callback) override;
-#endif
-
-  // Sets the display mode, which comes from the top-level browsing context and
-  // is applied to all widgets.
-  void SetDisplayMode(mojom::blink::DisplayMode);
-
-  base::Optional<gfx::Point> GetAndResetContextMenuLocation();
-
-  void BindWidgetCompositor(
-      mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) override;
-
-  void BindInputTargetClient(
-      mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver)
-      override;
-
-  // viz::mojom::blink::InputTargetClient:
-  void FrameSinkIdAt(const gfx::PointF& point,
-                     const uint64_t trace_id,
-                     FrameSinkIdAtCallback callback) override;
-
-  // Called when the FrameView for this Widget's local root is created.
-  void DidCreateLocalRootView();
-
-  void SetZoomLevel(double zoom_level);
-
-  // Enable or disable auto-resize. This is part of
-  // UpdateVisualProperties though tests may call to it more directly.
-  void SetAutoResizeMode(bool auto_resize,
-                         const gfx::Size& min_size_before_dsf,
-                         const gfx::Size& max_size_before_dsf,
-                         float device_scale_factor);
-
-  // Called when the View has auto resized.
-  void DidAutoResize(const gfx::Size& size);
-
-  // This method returns the focused frame belonging to this WebWidget, that
-  // is, a focused frame with the same local root as the one corresponding
-  // to this widget. It will return nullptr if no frame is focused or, the
-  // focused frame has a different local root.
-  LocalFrame* FocusedLocalFrameInWidget() const;
-
-  virtual void Trace(Visitor*) const;
-
-  // For when the embedder itself change scales on the page (e.g. devtools)
-  // and wants all of the content at the new scale to be crisp
-  void SetNeedsRecalculateRasterScales();
-
-  // Sets the background color to be filled in as gutter behind/around the
-  // painted content. Non-composited WebViews need not implement this, as they
-  // paint into another widget which has a background color of its own.
-  void SetBackgroundColor(SkColor color);
-
-  // Starts an animation of the page scale to a target scale factor and scroll
-  // offset.
-  // If use_anchor is true, destination is a point on the screen that will
-  // remain fixed for the duration of the animation.
-  // If use_anchor is false, destination is the final top-left scroll position.
-  void StartPageScaleAnimation(const gfx::Vector2d& destination,
-                               bool use_anchor,
-                               float new_page_scale,
-                               base::TimeDelta duration);
-
-  // Called to update if scroll events should be sent.
-  void SetHaveScrollEventHandlers(bool);
-
-  // Start deferring commits to the compositor, allowing document lifecycle
-  // updates without committing the layer tree. Commits are deferred
-  // until at most the given |timeout| has passed. If multiple calls are made
-  // when deferral is active then the initial timeout applies.
-  void StartDeferringCommits(base::TimeDelta timeout);
-  // Immediately stop deferring commits.
-  void StopDeferringCommits(cc::PaintHoldingCommitTrigger);
-
-  // Prevents any updates to the input for the layer tree, and the layer tree
-  // itself, and the layer tree from becoming visible.
-  std::unique_ptr<cc::ScopedDeferMainFrameUpdate> DeferMainFrameUpdate();
-
-  // Sets the amount that the top and bottom browser controls are showing, from
-  // 0 (hidden) to 1 (fully shown).
-  void SetBrowserControlsShownRatio(float top_ratio, float bottom_ratio);
-
-  // Set browser controls params. These params consist of top and bottom
-  // heights, min-heights, browser_controls_shrink_blink_size, and
-  // animate_browser_controls_height_changes. If
-  // animate_browser_controls_height_changes is set to true, changes to the
-  // browser controls height will be animated. If
-  // browser_controls_shrink_blink_size is set to true, then Blink shrunk the
-  // viewport clip layers by the top and bottom browser controls height. Top
-  // controls will translate the web page down and do not immediately scroll
-  // when hiding. The bottom controls scroll immediately and never translate the
-  // content (only clip it).
-  void SetBrowserControlsParams(cc::BrowserControlsParams params);
-
-  cc::LayerTreeDebugState GetLayerTreeDebugState();
-  void SetLayerTreeDebugState(const cc::LayerTreeDebugState& state);
-
-  // Ask compositor to composite a frame for testing. This will generate a
-  // BeginMainFrame, and update the document lifecycle.
-  void SynchronouslyCompositeForTesting(base::TimeTicks frame_time);
-
-  // Adjust the synchronous resize mode for testing. Normally resizes are
-  // asynchronous with sending the resize to the browser, however some tests
-  // still need the resize to happen in a synchronous fashion.
-  void UseSynchronousResizeModeForTesting(bool enable);
-
-  // Sets the device color space for testing.
-  void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
-
-  // Converts from DIPs to Blink coordinate space (ie. Viewport/Physical
-  // pixels).
-  gfx::Size DIPsToCeiledBlinkSpace(const gfx::Size& size);
-
-  void SetWindowRect(const gfx::Rect& window_rect);
-  void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
-
-  void SetToolTipText(const String& tooltip_text, TextDirection dir);
-
-  void ShowVirtualKeyboardOnElementFocus();
-  void ProcessTouchAction(WebTouchAction touch_action);
-
-  // Called when a gesture event has been processed.
-  void DidHandleGestureEvent(const WebGestureEvent& event);
-
-  // Called to update if pointerrawupdate events should be sent.
-  void SetHasPointerRawUpdateEventHandlers(bool);
-
-  // Called to update whether low latency input mode is enabled or not.
-  void SetNeedsLowLatencyInput(bool);
-
-  // Requests unbuffered (ie. low latency) input until a pointerup
-  // event occurs.
-  void RequestUnbufferedInputEvents();
-
-  // Requests unbuffered (ie. low latency) input due to debugger being
-  // attached. Debugger needs to paint when stopped in the event handler.
-  void SetNeedsUnbufferedInputForDebugger(bool);
-
-  // Called when the main frame navigates.
-  void DidNavigate();
-
-  // Called when the widget should get targeting input.
-  void SetMouseCapture(bool capture);
-
-  // Sets the current page scale factor and minimum / maximum limits. Both
-  // limits are initially 1 (no page scale allowed).
-  void SetPageScaleStateAndLimits(float page_scale_factor,
-                                  bool is_pinch_gesture_active,
-                                  float minimum,
-                                  float maximum);
-
-  // The value of the applied battery-savings META element in the document
-  // changed.
-  void BatterySavingsChanged(WebBatterySavingsFlags savings);
-
-  const viz::LocalSurfaceId& LocalSurfaceIdFromParent();
-  cc::LayerTreeHost* LayerTreeHost();
-
-  ScreenMetricsEmulator* DeviceEmulator();
-
-  // Calculates the selection bounds in the root frame. Returns bounds unchanged
-  // when there is no focused frame or no selection.
-  void CalculateSelectionBounds(gfx::Rect& anchor_in_root_frame,
-                                gfx::Rect& focus_in_root_frame);
-
-  // Returns if auto resize mode is enabled.
-  bool AutoResizeMode();
-
-  void SetScreenMetricsEmulationParameters(
-      bool enabled,
-      const blink::DeviceEmulationParams& params);
-  void SetScreenInfoAndSize(const blink::ScreenInfo& screen_info,
-                            const gfx::Size& widget_size,
-                            const gfx::Size& visible_viewport_size);
-
-  // Update the surface allocation information, compositor viewport rect and
-  // screen info on the widget.
-  void UpdateSurfaceAndScreenInfo(
-      const viz::LocalSurfaceId& new_local_surface_id,
-      const gfx::Rect& compositor_viewport_pixel_rect,
-      const ScreenInfo& new_screen_info);
-  // Similar to UpdateSurfaceAndScreenInfo but the surface allocation
-  // and compositor viewport rect remains the same.
-  void UpdateScreenInfo(const ScreenInfo& screen_info);
-  void UpdateSurfaceAndCompositorRect(
-      const viz::LocalSurfaceId& new_local_surface_id,
-      const gfx::Rect& compositor_viewport_pixel_rect);
-  void UpdateCompositorViewportRect(
-      const gfx::Rect& compositor_viewport_pixel_rect);
-  void SetWindowSegments(const std::vector<gfx::Rect>& window_segments);
-  viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point,
-                                         gfx::PointF* local_point);
-
-  // Set the pending window rect. For every SetPendingWindowRect
-  // call there must be an AckPendingWindowRect call.
-  void SetPendingWindowRect(const gfx::Rect& window_screen_rect);
-
-  // Clear a previously set pending window rect. For every SetPendingWindowRect
-  // call there must be an AckPendingWindowRect call.
-  void AckPendingWindowRect();
-
-  // Return the focused WebPlugin if there is one.
-  WebPlugin* GetFocusedPluginContainer();
-
- protected:
-  enum DragAction { kDragEnter, kDragOver };
-
-  // Consolidate some common code between starting a drag over a target and
-  // updating a drag over a target. If we're starting a drag, |isEntering|
-  // should be true.
-  DragOperation DragTargetDragEnterOrOver(const gfx::PointF& point_in_viewport,
-                                          const gfx::PointF& screen_point,
-                                          DragAction,
-                                          uint32_t key_modifiers);
-
-  // Helper function to call VisualViewport::viewportToRootFrame().
-  gfx::PointF ViewportToRootFrame(const gfx::PointF& point_in_viewport) const;
-
-  WebViewImpl* View() const;
-
-  // Returns the page object associated with this widget. This may be null when
-  // the page is shutting down, but will be valid at all other times.
-  Page* GetPage() const;
-
-  mojom::blink::FrameWidgetHost* GetAssociatedFrameWidgetHost() const;
-
-  // Helper function to process events while pointer locked.
-  void PointerLockMouseEvent(const WebCoalescedInputEvent&);
-  bool IsPointerLocked();
-
-  // The fullscreen granted status from the most recent VisualProperties update.
-  bool IsFullscreenGranted();
-
-  void NotifyPageScaleFactorChanged(float page_scale_factor,
-                                    bool is_pinch_gesture_active);
-
-  // Helper for notifying frame-level objects that care about input events.
-  // TODO: With some effort, this could be folded into a common implementation
-  // of WebViewImpl::HandleInputEvent and WebFrameWidgetImpl::HandleInputEvent.
-  void NotifyInputObservers(const WebCoalescedInputEvent& coalesced_event);
-
-  Frame* FocusedCoreFrame() const;
-
-  // Returns the currently focused `Element` in any `LocalFrame` owned by the
-  // associated `WebView`.
-  Element* FocusedElement() const;
-
-  // Perform a hit test for a point relative to the root frame of the page.
-  HitTestResult HitTestResultForRootFramePos(
-      const FloatPoint& pos_in_root_frame);
-
-  // Called during |UpdateVisualProperties| to apply the new size to the widget.
-  void ApplyVisualPropertiesSizing(const VisualProperties& visual_properties);
-
-  // Returns the current state of synchronous resize mode for testing.
-  bool SynchronousResizeModeForTestingEnabled();
-
-  // A copy of the web drop data object we received from the browser.
-  Member<DataObject> current_drag_data_;
-
-  bool doing_drag_and_drop_ = false;
-
-  // The available drag operations (copy, move link...) allowed by the source.
-  DragOperation operations_allowed_ = kDragOperationNone;
-
-  // The current drag operation as negotiated by the source and destination.
-  // When not equal to DragOperationNone, the drag data can be dropped onto the
-  // current drop target in this WebView (the drop target can accept the drop).
-  DragOperation drag_operation_ = kDragOperationNone;
-
-  // This field stores drag/drop related info for the event that is currently
-  // being handled. If the current event results in starting a drag/drop
-  // session, this info is sent to the browser along with other drag/drop info.
-  mojom::blink::DragEventSourceInfo possible_drag_event_info_;
-
-  // Base functionality all widgets have. This is a member as to avoid
-  // complicated inheritance structures.
-  std::unique_ptr<WidgetBase> widget_base_;
-
-  // The last seen page scale state, which comes from the main frame if we're
-  // in a child frame. This state is propagated through the RenderWidget tree
-  // passed to any new child RenderWidget.
-  float page_scale_factor_in_mainframe_ = 1.f;
-  bool is_pinch_gesture_active_in_mainframe_ = false;
-
-  // If set, the (plugin) element which has mouse capture.
-  // TODO(dtapuska): Move to private once all input handling is moved to
-  // base class.
-  Member<HTMLPlugInElement> mouse_capture_element_;
-
-  // The size of the widget in viewport coordinates. This is slightly different
-  // than the WebViewImpl::size_ since isn't set in auto resize mode.
-  base::Optional<gfx::Size> size_;
-
- private:
-  // PageWidgetEventHandler methods:
-  WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
-  void HandleMouseDown(LocalFrame&, const WebMouseEvent&) override;
-  void HandleMouseLeave(LocalFrame&, const WebMouseEvent&) override;
-  WebInputEventResult HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
-  WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
-  WebInputEventResult HandleMouseWheel(LocalFrame&,
-                                       const WebMouseWheelEvent&) override;
-  WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
-
-  WebInputEventResult HandleCapturedMouseEvent(const WebCoalescedInputEvent&);
-  void MouseContextMenu(const WebMouseEvent&);
-  void CancelDrag();
-  void RequestAnimationAfterDelayTimerFired(TimerBase*);
-  void PresentationCallbackForMeaningfulLayout(blink::WebSwapResult,
-                                               base::TimeTicks);
-
-  void ForEachRemoteFrameControlledByWidget(
-      const base::RepeatingCallback<void(RemoteFrame*)>& callback);
-
-  void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
-
-  // Finds the parameters required for scrolling the focused editable |element|
-  // into view. |out_rect_to_scroll| is used for recursive scrolling of the
-  // element into view and contains all or part of element's bounding box and
-  // always includes the caret and is with respect to absolute coordinates.
-  mojom::blink::ScrollIntoViewParamsPtr
-  GetScrollParamsForFocusedEditableElement(const Element& element,
-                                           PhysicalRect& out_rect_to_scroll);
-
-  static bool ignore_input_events_;
-
-  WebWidgetClient* client_;
-
-  const viz::FrameSinkId frame_sink_id_;
-
-  // WebFrameWidget is associated with a subtree of the frame tree,
-  // corresponding to a maximal connected tree of LocalFrames. This member
-  // points to the root of that subtree.
-  Member<WebLocalFrameImpl> local_root_;
-
-  mojom::blink::DisplayMode display_mode_;
-
-  WebVector<gfx::Rect> window_segments_;
-
-  // This is owned by the LayerTreeHostImpl, and should only be used on the
-  // compositor thread, so we keep the TaskRunner where you post tasks to
-  // make that happen.
-  base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> mutator_dispatcher_;
-  scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner_;
-
-  // The |paint_dispatcher_| should only be dereferenced on the
-  // |paint_task_runner_| (in practice this is the compositor thread). We keep a
-  // copy of it here to provide to new PaintWorkletProxyClient objects (which
-  // run on the worklet thread) so that they can talk to the
-  // PaintWorkletPaintDispatcher on the compositor thread.
-  base::WeakPtr<PaintWorkletPaintDispatcher> paint_dispatcher_;
-  scoped_refptr<base::SingleThreadTaskRunner> paint_task_runner_;
-
-  std::unique_ptr<TaskRunnerTimer<WebFrameWidgetBase>>
-      request_animation_after_delay_timer_;
-
-  // WebFrameWidgetBase is not tied to ExecutionContext
-  HeapMojoAssociatedRemote<mojom::blink::FrameWidgetHost,
-                           HeapMojoWrapperMode::kWithoutContextObserver>
-      frame_widget_host_{nullptr};
-  // WebFrameWidgetBase is not tied to ExecutionContext
-  HeapMojoAssociatedReceiver<mojom::blink::FrameWidget,
-                             WebFrameWidgetBase,
-                             HeapMojoWrapperMode::kWithoutContextObserver>
-      receiver_{this, nullptr};
-  HeapMojoReceiver<viz::mojom::blink::InputTargetClient,
-                   WebFrameWidgetBase,
-                   HeapMojoWrapperMode::kWithoutContextObserver>
-      input_target_receiver_{this, nullptr};
-
-  // Different consumers in the browser process makes different assumptions, so
-  // must always send the first IPC regardless of value.
-  base::Optional<bool> has_touch_handlers_;
-
-  Vector<mojom::blink::EditCommandPtr> edit_commands_;
-
-  base::Optional<gfx::Point> host_context_menu_location_;
-  uint32_t last_capture_sequence_number_ = 0u;
-
-  // Indicates whether tab-initiated fullscreen was granted.
-  bool is_fullscreen_granted_ = false;
-
-  // Indicates whether we need to consume scroll gestures to move cursor.
-  bool swipe_to_move_cursor_activated_ = false;
-
-  // Set when a measurement begins, reset when the measurement is taken.
-  base::Optional<base::TimeTicks> update_layers_start_time_;
-
-  // Metrics for gathering time for commit of compositor frame.
-  base::Optional<base::TimeTicks> commit_compositor_frame_start_time_;
-
-  // Present when emulation is enabled, only on a main frame's WebFrameWidget.
-  // Used to override values given from the browser such as ScreenInfo,
-  // WidgetScreenRect, WindowScreenRect, and the widget's size.
-  Member<ScreenMetricsEmulator> device_emulator_;
-
-  // keyPress events to be suppressed if the associated keyDown event was
-  // handled.
-  bool suppress_next_keypress_event_ = false;
-
-  // This struct contains data that is only valid for child local root widgets.
-  // You should use `child_data()` to access it.
-  struct ChildLocalRootData {
-    gfx::Rect compositor_visible_rect;
-    bool did_suspend_parsing = false;
-  } child_local_root_data_;
-
-  ChildLocalRootData& child_data() {
-    DCHECK(ForSubframe());
-    return child_local_root_data_;
-  }
-
-  // Web tests override the zoom factor in the renderer with this. We store it
-  // to keep the override if the browser passes along VisualProperties with the
-  // real device scale factor. A value of -INFINITY means this is ignored.
-  // It is always valid to read this variable but it can only be set for main
-  // frame widgets.
-  double zoom_level_for_testing_ = -INFINITY;
-
-  // Web tests override the device scale factor in the renderer with this. We
-  // store it to keep the override if the browser passes along VisualProperties
-  // with the real device scale factor. A value of 0.f means this is ignored.
-  // It is always valid to read this variable but it can only be set for main
-  // frame widgets.
-  float device_scale_factor_for_testing_ = 0;
-
-  // This struct contains data that is only valid for main frame widgets.
-  // You should use `main_data()` to access it.
-  struct MainFrameData {
-    // `UpdateLifecycle()` generates `WebMeaningfulLayout` events these
-    // variables track what events should be generated. They are only applicable
-    // for main frame widgets.
-    bool should_dispatch_first_visually_non_empty_layout = false;
-    bool should_dispatch_first_layout_after_finished_parsing = false;
-    bool should_dispatch_first_layout_after_finished_loading = false;
-    // Last background color sent to the browser. Only set for main frames.
-    base::Optional<SkColor> last_background_color;
-    // This bit is used to tell if this is a nested widget (an "inner web
-    // contents") like a <webview> or <portal> widget. If false, the widget is
-    // the top level widget.
-    bool is_for_nested_main_frame = false;
-
-    // In web tests, synchronous resizing mode may be used. Normally each
-    // widget's size is controlled by IPC from the browser. In synchronous
-    // resize mode the renderer controls the size directly, and IPCs from the
-    // browser must be ignored. This was deprecated but then later undeprecated,
-    // so it is now called unfortunate instead. See https://crbug.com/309760.
-    // When this is enabled the various size properties will be controlled
-    // directly when SetWindowRect() is called instead of needing a round trip
-    // through the browser. Note that SetWindowRectSynchronouslyForTesting()
-    // provides a secondary way to control the size of the FrameWidget
-    // independently from the renderer process, without the use of this mode,
-    // however it would be overridden by the browser if they disagree.
-    bool synchronous_resize_mode_for_testing = false;
-
-  } main_frame_data_;
-
-  MainFrameData& main_data() {
-    DCHECK(ForMainFrame());
-    return main_frame_data_;
-  }
-
-  const MainFrameData& main_data() const {
-    DCHECK(ForMainFrame());
-    return main_frame_data_;
-  }
-
-  // Whether this widget is for a child local root, or otherwise a main frame.
-  const bool is_for_child_local_root_;
-
-  // This stores the last hidden page popup. If a GestureTap attempts to open
-  // the popup that is closed by its previous GestureTapDown, the popup remains
-  // closed.
-  scoped_refptr<WebPagePopupImpl> last_hidden_page_popup_;
-
-  SelfKeepAlive<WebFrameWidgetBase> self_keep_alive_;
-
-  friend class WebViewImpl;
-  friend class ReportTimeSwapPromise;
-};
-
-template <>
-struct DowncastTraits<WebFrameWidgetBase> {
-  // All concrete implementations of WebFrameWidget are derived from
-  // WebFrameWidgetBase.
-  static bool AllowFrom(const WebFrameWidget& widget) { return true; }
-};
-
-}  // namespace blink
-
-#endif
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 ea26e1f..233ff4fd 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
@@ -33,68 +33,196 @@
 #include <memory>
 #include <utility>
 
-#include "base/auto_reset.h"
-#include "base/optional.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
-#include "cc/layers/picture_layer.h"
-#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/swap_promise.h"
+#include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
+#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
+#include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/web/web_autofill_client.h"
-#include "third_party/blink/public/web/web_element.h"
-#include "third_party/blink/public/web/web_frame_widget.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/public/web/web_performance.h"
 #include "third_party/blink/public/web/web_plugin.h"
-#include "third_party/blink/public/web/web_range.h"
+#include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/public/web/web_view_client.h"
 #include "third_party/blink/public/web/web_widget_client.h"
-#include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/editing/editor.h"
-#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
-#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
-#include "third_party/blink/renderer/core/editing/plain_text_range.h"
-#include "third_party/blink/renderer/core/editing/selection_template.h"
+#include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/events/current_input_event.h"
 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
+#include "third_party/blink/renderer/core/events/wheel_event.h"
 #include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
-#include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/remote_frame.h"
+#include "third_party/blink/renderer/core/frame/remote_frame_client.h"
+#include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
-#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
+#include "third_party/blink/renderer/core/html/portal/document_portals.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
 #include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/hit_test_location.h"
+#include "third_party/blink/renderer/core/layout/hit_test_request.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/loader/interactive_detector.h"
 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
+#include "third_party/blink/renderer/core/page/drag_actions.h"
+#include "third_party/blink/renderer/core/page/drag_controller.h"
+#include "third_party/blink/renderer/core/page/drag_data.h"
 #include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
 #include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/page_popup.h"
 #include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
-#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
+#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
+#include "third_party/blink/renderer/core/page/validation_message_client.h"
+#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
+#include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
+#include "third_party/blink/renderer/platform/keyboard_codes.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
+#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
 #include "third_party/blink/renderer/platform/widget/widget_base.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
+#include "ui/gfx/geometry/point_conversions.h"
+
+#if defined(OS_MAC)
+#include "third_party/blink/renderer/core/editing/substring_util.h"
+#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
+#include "ui/base/mojom/attributed_string.mojom-blink.h"
+#include "ui/gfx/geometry/point.h"
+#endif
+
+namespace WTF {
+template <>
+struct CrossThreadCopier<blink::WebReportTimeCallback>
+    : public CrossThreadCopierByValuePassThrough<blink::WebReportTimeCallback> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
+}  // namespace WTF
 
 namespace blink {
 
+namespace {
+
+const int kCaretPadding = 10;
+const float kIdealPaddingRatio = 0.3f;
+
+// Returns a rect which is offset and scaled accordingly to |base_rect|'s
+// location and size.
+FloatRect NormalizeRect(const IntRect& to_normalize, const IntRect& base_rect) {
+  FloatRect result(to_normalize);
+  result.SetLocation(
+      FloatPoint(to_normalize.Location() + (-base_rect.Location())));
+  result.Scale(1.0 / base_rect.Width(), 1.0 / base_rect.Height());
+  return result;
+}
+
+void ForEachLocalFrameControlledByWidget(
+    LocalFrame* frame,
+    const base::RepeatingCallback<void(WebLocalFrame*)>& callback) {
+  callback.Run(WebLocalFrameImpl::FromFrame(frame));
+  for (Frame* child = frame->FirstChild(); child;
+       child = child->NextSibling()) {
+    if (child->IsLocalFrame()) {
+      ForEachLocalFrameControlledByWidget(DynamicTo<LocalFrame>(child),
+                                          callback);
+    }
+  }
+}
+
+// Iterate the remote children that will be controlled by the widget. Skip over
+// any RemoteFrames have have another LocalFrame root as their parent.
+void ForEachRemoteFrameChildrenControlledByWidget(
+    Frame* frame,
+    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+  for (Frame* child = frame->Tree().FirstChild(); child;
+       child = child->Tree().NextSibling()) {
+    if (auto* remote_frame = DynamicTo<RemoteFrame>(child)) {
+      callback.Run(remote_frame);
+      ForEachRemoteFrameChildrenControlledByWidget(remote_frame, callback);
+    } else if (auto* local_frame = DynamicTo<LocalFrame>(child)) {
+      // If iteration arrives at a local root then don't descend as it will be
+      // controlled by another widget.
+      if (!local_frame->IsLocalRoot()) {
+        ForEachRemoteFrameChildrenControlledByWidget(local_frame, callback);
+      }
+    }
+  }
+
+  // Iterate on any portals owned by a local frame.
+  if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
+    if (Document* document = local_frame->GetDocument()) {
+      for (PortalContents* portal :
+           DocumentPortals::From(*document).GetPortals()) {
+        if (RemoteFrame* remote_frame = portal->GetFrame())
+          callback.Run(remote_frame);
+      }
+    }
+  }
+}
+
+viz::FrameSinkId GetRemoteFrameSinkId(const HitTestResult& result) {
+  Node* node = result.InnerNode();
+  auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node);
+  if (!frame_owner || !frame_owner->ContentFrame() ||
+      !frame_owner->ContentFrame()->IsRemoteFrame())
+    return viz::FrameSinkId();
+
+  RemoteFrame* remote_frame = To<RemoteFrame>(frame_owner->ContentFrame());
+  if (remote_frame->IsIgnoredForHitTest())
+    return viz::FrameSinkId();
+  LayoutObject* object = result.GetLayoutObject();
+  DCHECK(object);
+  if (!object->IsBox())
+    return viz::FrameSinkId();
+
+  IntPoint local_point = RoundedIntPoint(result.LocalPoint());
+  if (!To<LayoutBox>(object)->ComputedCSSContentBoxRect().Contains(local_point))
+    return viz::FrameSinkId();
+
+  return remote_frame->GetFrameSinkId();
+}
+
+}  // namespace
+
 // WebFrameWidget ------------------------------------------------------------
 
-static CreateWebViewFrameWidgetFunction g_create_web_view_frame_widget =
-    nullptr;
+static CreateMainFrameWebFrameWidgetFunction
+    g_create_main_frame_web_frame_widget = nullptr;
 
-void InstallCreateWebViewFrameWidgetHook(
-    CreateWebViewFrameWidgetFunction create_widget) {
-  g_create_web_view_frame_widget = create_widget;
+void InstallCreateMainFrameWebFrameWidgetHook(
+    CreateMainFrameWebFrameWidgetFunction create_widget) {
+  g_create_main_frame_web_frame_widget = create_widget;
 }
 
 WebFrameWidget* WebFrameWidget::CreateForMainFrame(
@@ -116,7 +244,7 @@
   DCHECK(!main_frame->Parent());  // This is the main frame.
 
   // Grabs the WebViewImpl associated with the |main_frame|, which will then
-  // be wrapped by the WebViewFrameWidget, with calls being forwarded to the
+  // be wrapped by the WebFrameWidgetImpl, with calls being forwarded to the
   // |main_frame|'s WebViewImpl.
   // Note: this can't DCHECK that the view's main frame points to
   // |main_frame|, as provisional frames violate this precondition.
@@ -124,26 +252,29 @@
   DCHECK(main_frame_impl.ViewImpl());
   WebViewImpl& web_view_impl = *main_frame_impl.ViewImpl();
 
-  WebViewFrameWidget* widget = nullptr;
-  if (g_create_web_view_frame_widget) {
-    widget = g_create_web_view_frame_widget(
-        base::PassKey<WebFrameWidget>(), *client, web_view_impl,
+  WebFrameWidgetImpl* widget = nullptr;
+  if (g_create_main_frame_web_frame_widget) {
+    widget = g_create_main_frame_web_frame_widget(
+        base::PassKey<WebFrameWidget>(), *client,
         std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
         std::move(mojo_widget_host), std::move(mojo_widget),
         main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
-        frame_sink_id, is_for_nested_main_frame, hidden, never_composited);
+        frame_sink_id, hidden, never_composited,
+        /*is_for_child_local_root=*/false, is_for_nested_main_frame);
   } else {
     // Note: this isn't a leak, as the object has a self-reference that the
     // caller needs to release by calling Close().
     // TODO(dcheng): Remove the special bridge class for main frame widgets.
-    widget = MakeGarbageCollected<WebViewFrameWidget>(
-        base::PassKey<WebFrameWidget>(), *client, web_view_impl,
+    widget = MakeGarbageCollected<WebFrameWidgetImpl>(
+        base::PassKey<WebFrameWidget>(), *client,
         std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
         std::move(mojo_widget_host), std::move(mojo_widget),
         main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
-        frame_sink_id, is_for_nested_main_frame, hidden, never_composited);
+        frame_sink_id, hidden, never_composited,
+        /*is_for_child_local_root=*/false, is_for_nested_main_frame);
   }
   widget->BindLocalRoot(*main_frame);
+  web_view_impl.SetMainFrameViewWidget(widget);
   return widget;
 }
 
@@ -175,11 +306,14 @@
       std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
       std::move(mojo_widget_host), std::move(mojo_widget),
       local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
-      frame_sink_id, hidden, never_composited);
+      frame_sink_id, hidden, never_composited, /*is_for_child_local_root=*/true,
+      /*is_for_nested_main_frame=*/false);
   widget->BindLocalRoot(*local_root);
   return widget;
 }
 
+bool WebFrameWidgetImpl::ignore_input_events_ = false;
+
 WebFrameWidgetImpl::WebFrameWidgetImpl(
     base::PassKey<WebFrameWidget>,
     WebWidgetClient& client,
@@ -194,19 +328,3811 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     const viz::FrameSinkId& frame_sink_id,
     bool hidden,
-    bool never_composited)
-    : WebFrameWidgetBase(client,
-                         std::move(frame_widget_host),
-                         std::move(frame_widget),
-                         std::move(widget_host),
-                         std::move(widget),
-                         std::move(task_runner),
-                         frame_sink_id,
-                         hidden,
-                         never_composited,
-                         /*is_for_child_local_root=*/true,
-                         /*is_for_nested_main_frame=*/false) {}
+    bool never_composited,
+    bool is_for_child_local_root,
+    bool is_for_nested_main_frame)
+    : widget_base_(std::make_unique<WidgetBase>(this,
+                                                std::move(widget_host),
+                                                std::move(widget),
+                                                task_runner,
+                                                hidden,
+                                                never_composited,
+                                                is_for_child_local_root)),
+      client_(&client),
+      frame_sink_id_(frame_sink_id),
+      is_for_child_local_root_(is_for_child_local_root),
+      self_keep_alive_(PERSISTENT_FROM_HERE, this) {
+  DCHECK(task_runner);
+  if (is_for_nested_main_frame)
+    main_data().is_for_nested_main_frame = is_for_nested_main_frame;
+  frame_widget_host_.Bind(std::move(frame_widget_host), task_runner);
+  receiver_.Bind(std::move(frame_widget), task_runner);
+}
 
-WebFrameWidgetImpl::~WebFrameWidgetImpl() = default;
+WebFrameWidgetImpl::~WebFrameWidgetImpl() {
+  // Ensure that Close is called and we aren't releasing |widget_base_| in the
+  // destructor.
+  // TODO(crbug.com/1139104): This CHECK can be changed to a DCHECK once
+  // the issue is solved.
+  CHECK(!widget_base_);
+}
+
+void WebFrameWidgetImpl::BindLocalRoot(WebLocalFrame& local_root) {
+  local_root_ = To<WebLocalFrameImpl>(local_root);
+  local_root_->SetFrameWidget(this);
+  request_animation_after_delay_timer_ =
+      std::make_unique<TaskRunnerTimer<WebFrameWidgetImpl>>(
+          local_root.GetTaskRunner(TaskType::kInternalDefault), this,
+          &WebFrameWidgetImpl::RequestAnimationAfterDelayTimerFired);
+}
+
+bool WebFrameWidgetImpl::ForTopMostMainFrame() const {
+  return ForMainFrame() && !main_data().is_for_nested_main_frame;
+}
+
+void WebFrameWidgetImpl::SetIsNestedMainFrameWidget(bool is_nested) {
+  main_data().is_for_nested_main_frame = is_nested;
+}
+
+void WebFrameWidgetImpl::Close(
+    scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
+  LocalFrameView* frame_view;
+  if (is_for_child_local_root_) {
+    frame_view = LocalRootImpl()->GetFrame()->View();
+  } else {
+    // Scrolling for the root frame is special we need to pass null indicating
+    // we are at the top of the tree when setting up the Animation. Which will
+    // cause ownership of the timeline and animation host.
+    // See ScrollingCoordinator::AnimationHostInitialized.
+    frame_view = nullptr;
+  }
+  GetPage()->WillCloseAnimationHost(frame_view);
+
+  if (ForMainFrame()) {
+    // Closing the WebFrameWidgetImpl happens in response to the local main
+    // frame being detached from the Page/WebViewImpl.
+    View()->SetMainFrameViewWidget(nullptr);
+  }
+
+  mutator_dispatcher_ = nullptr;
+  local_root_->SetFrameWidget(nullptr);
+  local_root_ = nullptr;
+  client_ = nullptr;
+  request_animation_after_delay_timer_.reset();
+  widget_base_->Shutdown(std::move(cleanup_runner));
+  widget_base_.reset();
+  receiver_.reset();
+  input_target_receiver_.reset();
+  self_keep_alive_.Clear();
+}
+
+WebLocalFrame* WebFrameWidgetImpl::LocalRoot() const {
+  return local_root_;
+}
+
+WebRect WebFrameWidgetImpl::ComputeBlockBound(
+    const gfx::Point& point_in_root_frame,
+    bool ignore_clipping) const {
+  HitTestLocation location(local_root_->GetFrameView()->ConvertFromRootFrame(
+      PhysicalOffset(IntPoint(point_in_root_frame))));
+  HitTestRequest::HitTestRequestType hit_type =
+      HitTestRequest::kReadOnly | HitTestRequest::kActive |
+      (ignore_clipping ? HitTestRequest::kIgnoreClipping : 0);
+  HitTestResult result =
+      local_root_->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+          location, hit_type);
+  result.SetToShadowHostIfInRestrictedShadowRoot();
+
+  Node* node = result.InnerNodeOrImageMapImage();
+  if (!node)
+    return WebRect();
+
+  // Find the block type node based on the hit node.
+  // FIXME: This wants to walk flat tree with
+  // LayoutTreeBuilderTraversal::parent().
+  while (node &&
+         (!node->GetLayoutObject() || node->GetLayoutObject()->IsInline()))
+    node = LayoutTreeBuilderTraversal::Parent(*node);
+
+  // Return the bounding box in the root frame's coordinate space.
+  if (node) {
+    IntRect absolute_rect = node->GetLayoutObject()->AbsoluteBoundingBoxRect();
+    LocalFrame* frame = node->GetDocument().GetFrame();
+    return frame->View()->ConvertToRootFrame(absolute_rect);
+  }
+  return WebRect();
+}
+
+void WebFrameWidgetImpl::DragTargetDragEnter(
+    const WebDragData& web_drag_data,
+    const gfx::PointF& point_in_viewport,
+    const gfx::PointF& screen_point,
+    DragOperationsMask operations_allowed,
+    uint32_t key_modifiers,
+    DragTargetDragEnterCallback callback) {
+  DCHECK(!current_drag_data_);
+
+  current_drag_data_ = DataObject::Create(web_drag_data);
+  operations_allowed_ = operations_allowed;
+
+  blink::DragOperation operation = DragTargetDragEnterOrOver(
+      point_in_viewport, screen_point, kDragEnter, key_modifiers);
+  std::move(callback).Run(operation);
+}
+
+void WebFrameWidgetImpl::DragTargetDragOver(
+    const gfx::PointF& point_in_viewport,
+    const gfx::PointF& screen_point,
+    DragOperationsMask operations_allowed,
+    uint32_t key_modifiers,
+    DragTargetDragOverCallback callback) {
+  operations_allowed_ = operations_allowed;
+
+  blink::DragOperation operation = DragTargetDragEnterOrOver(
+      point_in_viewport, screen_point, kDragOver, key_modifiers);
+  std::move(callback).Run(operation);
+}
+
+void WebFrameWidgetImpl::DragTargetDragLeave(
+    const gfx::PointF& point_in_viewport,
+    const gfx::PointF& screen_point) {
+  DCHECK(current_drag_data_);
+
+  // TODO(paulmeyer): It shouldn't be possible for |current_drag_data_| to be
+  // null here, but this is somehow happening (rarely). This suggests that in
+  // some cases drag-leave is happening before drag-enter, which should be
+  // impossible. This needs to be investigated further. Once fixed, the extra
+  // check for |!current_drag_data_| should be removed. (crbug.com/671152)
+  if (IgnoreInputEvents() || !current_drag_data_) {
+    CancelDrag();
+    return;
+  }
+
+  gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+  DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
+                     FloatPoint(screen_point), operations_allowed_);
+
+  GetPage()->GetDragController().DragExited(&drag_data,
+                                            *local_root_->GetFrame());
+
+  // FIXME: why is the drag scroll timer not stopped here?
+
+  drag_operation_ = kDragOperationNone;
+  current_drag_data_ = nullptr;
+}
+
+void WebFrameWidgetImpl::DragTargetDrop(const WebDragData& web_drag_data,
+                                        const gfx::PointF& point_in_viewport,
+                                        const gfx::PointF& screen_point,
+                                        uint32_t key_modifiers) {
+  gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+
+  DCHECK(current_drag_data_);
+  current_drag_data_ = DataObject::Create(web_drag_data);
+
+  // If this webview transitions from the "drop accepting" state to the "not
+  // accepting" state, then our IPC message reply indicating that may be in-
+  // flight, or else delayed by javascript processing in this webview.  If a
+  // drop happens before our IPC reply has reached the browser process, then
+  // the browser forwards the drop to this webview.  So only allow a drop to
+  // proceed if our webview m_dragOperation state is not DragOperationNone.
+
+  if (drag_operation_ == kDragOperationNone) {
+    // IPC RACE CONDITION: do not allow this drop.
+    DragTargetDragLeave(point_in_viewport, screen_point);
+    return;
+  }
+
+  if (!IgnoreInputEvents()) {
+    current_drag_data_->SetModifiers(key_modifiers);
+    DragData drag_data(current_drag_data_.Get(),
+                       FloatPoint(point_in_root_frame),
+                       FloatPoint(screen_point), operations_allowed_);
+
+    GetPage()->GetDragController().PerformDrag(&drag_data,
+                                               *local_root_->GetFrame());
+  }
+  drag_operation_ = kDragOperationNone;
+  current_drag_data_ = nullptr;
+}
+
+void WebFrameWidgetImpl::DragSourceEndedAt(const gfx::PointF& point_in_viewport,
+                                           const gfx::PointF& screen_point,
+                                           DragOperation operation) {
+  if (!local_root_) {
+    // We should figure out why |local_root_| could be nullptr
+    // (https://crbug.com/792345).
+    return;
+  }
+
+  if (IgnoreInputEvents()) {
+    CancelDrag();
+    return;
+  }
+  gfx::PointF point_in_root_frame(
+      GetPage()->GetVisualViewport().ViewportToRootFrame(
+          FloatPoint(point_in_viewport)));
+
+  WebMouseEvent fake_mouse_move(
+      WebInputEvent::Type::kMouseMove, point_in_root_frame, screen_point,
+      WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
+      base::TimeTicks::Now());
+  fake_mouse_move.SetFrameScale(1);
+  local_root_->GetFrame()->GetEventHandler().DragSourceEndedAt(fake_mouse_move,
+                                                               operation);
+}
+
+void WebFrameWidgetImpl::DragSourceSystemDragEnded() {
+  CancelDrag();
+}
+
+void WebFrameWidgetImpl::SetBackgroundOpaque(bool opaque) {
+  if (opaque) {
+    View()->ClearBaseBackgroundColorOverride();
+    View()->ClearBackgroundColorOverride();
+  } else {
+    View()->SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT);
+    View()->SetBackgroundColorOverride(SK_ColorTRANSPARENT);
+  }
+}
+
+void WebFrameWidgetImpl::SetTextDirection(base::i18n::TextDirection direction) {
+  LocalFrame* focusedFrame = FocusedLocalFrameInWidget();
+  if (focusedFrame)
+    focusedFrame->SetTextDirection(direction);
+}
+
+void WebFrameWidgetImpl::SetInheritedEffectiveTouchActionForSubFrame(
+    TouchAction touch_action) {
+  DCHECK(ForSubframe());
+  LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
+}
+
+void WebFrameWidgetImpl::UpdateRenderThrottlingStatusForSubFrame(
+    bool is_throttled,
+    bool subtree_throttled) {
+  DCHECK(ForSubframe());
+  LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
+      is_throttled, subtree_throttled, true);
+}
+
+#if defined(OS_MAC)
+void WebFrameWidgetImpl::GetStringAtPoint(const gfx::Point& point_in_local_root,
+                                          GetStringAtPointCallback callback) {
+  gfx::Point baseline_point;
+  ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
+  NSAttributedString* string = SubstringUtil::AttributedWordAtPoint(
+      this, point_in_local_root, baseline_point);
+  if (string)
+    attributed_string = ui::mojom::blink::AttributedString::From(string);
+
+  std::move(callback).Run(std::move(attributed_string), baseline_point);
+}
+#endif
+
+void WebFrameWidgetImpl::BindWidgetCompositor(
+    mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
+  widget_base_->BindWidgetCompositor(std::move(receiver));
+}
+
+void WebFrameWidgetImpl::BindInputTargetClient(
+    mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver) {
+  DCHECK(!input_target_receiver_.is_bound());
+  input_target_receiver_.Bind(
+      std::move(receiver),
+      local_root_->GetTaskRunner(TaskType::kInternalDefault));
+}
+
+void WebFrameWidgetImpl::FrameSinkIdAt(const gfx::PointF& point,
+                                       const uint64_t trace_id,
+                                       FrameSinkIdAtCallback callback) {
+  TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Event.Pipeline",
+                         TRACE_ID_GLOBAL(trace_id),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+                         "step", "FrameSinkIdAt");
+
+  gfx::PointF local_point;
+  viz::FrameSinkId id = GetFrameSinkIdAtPoint(point, &local_point);
+  std::move(callback).Run(id, local_point);
+}
+
+viz::FrameSinkId WebFrameWidgetImpl::GetFrameSinkIdAtPoint(
+    const gfx::PointF& point_in_dips,
+    gfx::PointF* local_point_in_dips) {
+  HitTestResult result =
+      CoreHitTestResultAt(widget_base_->DIPsToBlinkSpace(point_in_dips));
+
+  Node* result_node = result.InnerNode();
+  *local_point_in_dips = gfx::PointF(point_in_dips);
+
+  // TODO(crbug.com/797828): When the node is null the caller may
+  // need to do extra checks. Like maybe update the layout and then
+  // call the hit-testing API. Either way it might be better to have
+  // a DCHECK for the node rather than a null check here.
+  if (!result_node) {
+    return frame_sink_id_;
+  }
+
+  viz::FrameSinkId remote_frame_sink_id = GetRemoteFrameSinkId(result);
+  if (remote_frame_sink_id.is_valid()) {
+    FloatPoint local_point = FloatPoint(result.LocalPoint());
+    LayoutObject* object = result.GetLayoutObject();
+    if (auto* box = DynamicTo<LayoutBox>(object))
+      local_point.MoveBy(-FloatPoint(box->PhysicalContentBoxOffset()));
+
+    *local_point_in_dips =
+        widget_base_->BlinkSpaceToDIPs(gfx::PointF(local_point));
+    return remote_frame_sink_id;
+  }
+
+  // Return the FrameSinkId for the current widget if the point did not hit
+  // test to a remote frame, or the point is outside of the remote frame's
+  // content box, or the remote frame doesn't have a valid FrameSinkId yet.
+  return frame_sink_id_;
+}
+
+gfx::RectF WebFrameWidgetImpl::BlinkSpaceToDIPs(const gfx::RectF& rect) {
+  return widget_base_->BlinkSpaceToDIPs(rect);
+}
+
+gfx::Rect WebFrameWidgetImpl::BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) {
+  return widget_base_->BlinkSpaceToEnclosedDIPs(rect);
+}
+
+gfx::Size WebFrameWidgetImpl::BlinkSpaceToFlooredDIPs(const gfx::Size& size) {
+  return widget_base_->BlinkSpaceToFlooredDIPs(size);
+}
+
+gfx::RectF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::RectF& rect) {
+  return widget_base_->DIPsToBlinkSpace(rect);
+}
+
+gfx::PointF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::PointF& point) {
+  return widget_base_->DIPsToBlinkSpace(point);
+}
+
+gfx::Point WebFrameWidgetImpl::DIPsToRoundedBlinkSpace(
+    const gfx::Point& point) {
+  return widget_base_->DIPsToRoundedBlinkSpace(point);
+}
+
+float WebFrameWidgetImpl::DIPsToBlinkSpace(float scalar) {
+  return widget_base_->DIPsToBlinkSpace(scalar);
+}
+
+gfx::Size WebFrameWidgetImpl::DIPsToCeiledBlinkSpace(const gfx::Size& size) {
+  return widget_base_->DIPsToCeiledBlinkSpace(size);
+}
+
+void WebFrameWidgetImpl::SetActive(bool active) {
+  View()->SetIsActive(active);
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
+    const WebKeyboardEvent& event) {
+  DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
+         (event.GetType() == WebInputEvent::Type::kKeyDown) ||
+         (event.GetType() == WebInputEvent::Type::kKeyUp));
+
+  // Please refer to the comments explaining the m_suppressNextKeypressEvent
+  // member.
+  // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
+  // Webkit. A keyDown event is typically associated with a keyPress(char)
+  // event and a keyUp event. We reset this flag here as this is a new keyDown
+  // event.
+  suppress_next_keypress_event_ = false;
+
+  // If there is a popup open, it should be the one processing the event,
+  // not the page.
+  scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
+  if (page_popup) {
+    page_popup->HandleKeyEvent(event);
+    if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
+      suppress_next_keypress_event_ = true;
+    }
+    return WebInputEventResult::kHandledSystem;
+  }
+
+  auto* frame = DynamicTo<LocalFrame>(FocusedCoreFrame());
+  if (!frame)
+    return WebInputEventResult::kNotHandled;
+
+  WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
+  if (result != WebInputEventResult::kNotHandled) {
+    if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
+      // Suppress the next keypress event unless the focused node is a plugin
+      // node.  (Flash needs these keypress events to handle non-US keyboards.)
+      Element* element = FocusedElement();
+      if (element && element->GetLayoutObject() &&
+          element->GetLayoutObject()->IsEmbeddedObject()) {
+        if (event.windows_key_code == VKEY_TAB) {
+          // If the plugin supports keyboard focus then we should not send a tab
+          // keypress event.
+          WebPluginContainerImpl* plugin_view =
+              To<LayoutEmbeddedContent>(element->GetLayoutObject())->Plugin();
+          if (plugin_view && plugin_view->SupportsKeyboardFocus()) {
+            suppress_next_keypress_event_ = true;
+          }
+        }
+      } else {
+        suppress_next_keypress_event_ = true;
+      }
+    }
+    return result;
+  }
+
+#if !defined(OS_MAC)
+  const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
+#if defined(OS_WIN)
+      WebInputEvent::Type::kKeyUp;
+#else
+      WebInputEvent::Type::kRawKeyDown;
+#endif
+  const WebInputEvent::Type kShiftF10TriggeringEventType =
+      WebInputEvent::Type::kRawKeyDown;
+
+  bool is_unmodified_menu_key =
+      !(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
+      event.windows_key_code == VKEY_APPS;
+  bool is_shift_f10 = (event.GetModifiers() & WebInputEvent::kInputModifiers) ==
+                          WebInputEvent::kShiftKey &&
+                      event.windows_key_code == VKEY_F10;
+  if ((is_unmodified_menu_key &&
+       event.GetType() == kContextMenuKeyTriggeringEventType) ||
+      (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) {
+    View()->SendContextMenuEvent();
+    return WebInputEventResult::kHandledSystem;
+  }
+#endif  // !defined(OS_MAC)
+
+  return WebInputEventResult::kNotHandled;
+}
+
+void WebFrameWidgetImpl::HandleMouseDown(LocalFrame& local_root,
+                                         const WebMouseEvent& event) {
+  WebViewImpl* view_impl = View();
+  // If there is a popup open, close it as the user is clicking on the page
+  // (outside of the popup). We also save it so we can prevent a click on an
+  // element from immediately reopening the same popup.
+  scoped_refptr<WebPagePopupImpl> page_popup;
+  if (event.button == WebMouseEvent::Button::kLeft) {
+    page_popup = view_impl->GetPagePopup();
+    view_impl->CancelPagePopup();
+  }
+
+  // Take capture on a mouse down on a plugin so we can send it mouse events.
+  // If the hit node is a plugin but a scrollbar is over it don't start mouse
+  // capture because it will interfere with the scrollbar receiving events.
+  PhysicalOffset point(LayoutUnit(event.PositionInWidget().x()),
+                       LayoutUnit(event.PositionInWidget().y()));
+  if (event.button == WebMouseEvent::Button::kLeft) {
+    HitTestLocation location(
+        LocalRootImpl()->GetFrameView()->ConvertFromRootFrame(point));
+    HitTestResult result(
+        LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+            location));
+    result.SetToShadowHostIfInRestrictedShadowRoot();
+    Node* hit_node = result.InnerNode();
+    auto* html_element = DynamicTo<HTMLElement>(hit_node);
+    if (!result.GetScrollbar() && hit_node && hit_node->GetLayoutObject() &&
+        hit_node->GetLayoutObject()->IsEmbeddedObject() && html_element &&
+        html_element->IsPluginElement()) {
+      mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
+      SetMouseCapture(true);
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
+                                        TRACE_ID_LOCAL(this));
+    }
+  }
+
+  PageWidgetEventHandler::HandleMouseDown(local_root, event);
+  // PageWidgetEventHandler may have detached the frame.
+  if (!LocalRootImpl())
+    return;
+
+  if (view_impl->GetPagePopup() && page_popup &&
+      view_impl->GetPagePopup()->HasSamePopupClient(page_popup.get())) {
+    // That click triggered a page popup that is the same as the one we just
+    // closed.  It needs to be closed.
+    view_impl->CancelPagePopup();
+  }
+
+  // Dispatch the contextmenu event regardless of if the click was swallowed.
+  if (!GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
+#if defined(OS_MAC)
+    if (event.button == WebMouseEvent::Button::kRight ||
+        (event.button == WebMouseEvent::Button::kLeft &&
+         event.GetModifiers() & WebMouseEvent::kControlKey))
+      MouseContextMenu(event);
+#else
+    if (event.button == WebMouseEvent::Button::kRight)
+      MouseContextMenu(event);
+#endif
+  }
+}
+
+void WebFrameWidgetImpl::HandleMouseLeave(LocalFrame& local_root,
+                                          const WebMouseEvent& event) {
+  View()->SetMouseOverURL(WebURL());
+  PageWidgetEventHandler::HandleMouseLeave(local_root, event);
+  // PageWidgetEventHandler may have detached the frame.
+}
+
+void WebFrameWidgetImpl::MouseContextMenu(const WebMouseEvent& event) {
+  GetPage()->GetContextMenuController().ClearContextMenu();
+
+  WebMouseEvent transformed_event =
+      TransformWebMouseEvent(LocalRootImpl()->GetFrameView(), event);
+  transformed_event.menu_source_type = kMenuSourceMouse;
+
+  // Find the right target frame. See issue 1186900.
+  HitTestResult result = HitTestResultForRootFramePos(
+      FloatPoint(transformed_event.PositionInRootFrame()));
+  Frame* target_frame;
+  if (result.InnerNodeOrImageMapImage())
+    target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
+  else
+    target_frame = GetPage()->GetFocusController().FocusedOrMainFrame();
+
+  // This will need to be changed to a nullptr check when focus control
+  // is refactored, at which point focusedOrMainFrame will never return a
+  // RemoteFrame.
+  // See https://crbug.com/341918.
+  LocalFrame* target_local_frame = DynamicTo<LocalFrame>(target_frame);
+  if (!target_local_frame)
+    return;
+
+  {
+    ContextMenuAllowedScope scope;
+    target_local_frame->GetEventHandler().SendContextMenuEvent(
+        transformed_event);
+  }
+  // Actually showing the context menu is handled by the ContextMenuClient
+  // implementation...
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleMouseUp(
+    LocalFrame& local_root,
+    const WebMouseEvent& event) {
+  WebInputEventResult result =
+      PageWidgetEventHandler::HandleMouseUp(local_root, event);
+  // PageWidgetEventHandler may have detached the frame.
+  if (!LocalRootImpl())
+    return result;
+
+  if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
+    // Dispatch the contextmenu event regardless of if the click was swallowed.
+    // On Mac/Linux, we handle it on mouse down, not up.
+    if (event.button == WebMouseEvent::Button::kRight)
+      MouseContextMenu(event);
+  }
+  return result;
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
+    const WebGestureEvent& event) {
+  WebInputEventResult event_result = WebInputEventResult::kNotHandled;
+
+  // Fling events are not sent to the renderer.
+  CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingStart);
+  CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingCancel);
+
+  WebViewImpl* web_view = View();
+
+  LocalFrame* frame = LocalRootImpl()->GetFrame();
+  WebGestureEvent scaled_event = TransformWebGestureEvent(frame->View(), event);
+
+  // Special handling for double tap and scroll events as we don't want to
+  // hit test for them.
+  switch (event.GetType()) {
+    case WebInputEvent::Type::kGestureDoubleTap:
+      if (web_view->SettingsImpl()->DoubleTapToZoomEnabled() &&
+          web_view->MinimumPageScaleFactor() !=
+              web_view->MaximumPageScaleFactor()) {
+        IntPoint pos_in_local_frame_root =
+            FlooredIntPoint(scaled_event.PositionInRootFrame());
+        auto block_bounds =
+            gfx::Rect(ComputeBlockBound(pos_in_local_frame_root, false));
+
+        if (ForMainFrame()) {
+          web_view->AnimateDoubleTapZoom(pos_in_local_frame_root,
+                                         WebRect(block_bounds));
+        } else {
+          // This sends the tap point and bounds to the main frame renderer via
+          // the browser, where their coordinates will be transformed into the
+          // main frame's coordinate space.
+          GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
+              pos_in_local_frame_root, block_bounds);
+        }
+      }
+      event_result = WebInputEventResult::kHandledSystem;
+      DidHandleGestureEvent(event);
+      return event_result;
+    case WebInputEvent::Type::kGestureScrollBegin:
+    case WebInputEvent::Type::kGestureScrollEnd:
+    case WebInputEvent::Type::kGestureScrollUpdate:
+      // If we are getting any scroll toss close any page popup that is open.
+      web_view->CancelPagePopup();
+
+      // Scrolling-related gesture events invoke EventHandler recursively for
+      // each frame down the chain, doing a single-frame hit-test per frame.
+      // This matches handleWheelEvent.  Perhaps we could simplify things by
+      // rewriting scroll handling to work inner frame out, and then unify with
+      // other gesture events.
+      event_result =
+          frame->GetEventHandler().HandleGestureScrollEvent(scaled_event);
+      DidHandleGestureEvent(event);
+      return event_result;
+    default:
+      break;
+  }
+
+  // Hit test across all frames and do touch adjustment as necessary for the
+  // event type.
+  GestureEventWithHitTestResults targeted_event =
+      frame->GetEventHandler().TargetGestureEvent(scaled_event);
+
+  // Link highlight animations are only for the main frame.
+  if (ForMainFrame()) {
+    // Handle link highlighting outside the main switch to avoid getting lost in
+    // the complicated set of cases handled below.
+    switch (scaled_event.GetType()) {
+      case WebInputEvent::Type::kGestureShowPress:
+        // Queue a highlight animation, then hand off to regular handler.
+        web_view->EnableTapHighlightAtPoint(targeted_event);
+        break;
+      case WebInputEvent::Type::kGestureTapCancel:
+      case WebInputEvent::Type::kGestureTap:
+      case WebInputEvent::Type::kGestureLongPress:
+        GetPage()->GetLinkHighlight().StartHighlightAnimationIfNeeded();
+        break;
+      default:
+        break;
+    }
+  }
+
+  switch (scaled_event.GetType()) {
+    case WebInputEvent::Type::kGestureTap: {
+      {
+        ContextMenuAllowedScope scope;
+        event_result =
+            frame->GetEventHandler().HandleGestureEvent(targeted_event);
+      }
+
+      if (web_view->GetPagePopup() && last_hidden_page_popup_ &&
+          web_view->GetPagePopup()->HasSamePopupClient(
+              last_hidden_page_popup_.get())) {
+        // The tap triggered a page popup that is the same as the one we just
+        // closed. It needs to be closed.
+        web_view->CancelPagePopup();
+      }
+      // Don't have this value persist outside of a single tap gesture, plus
+      // we're done with it now.
+      last_hidden_page_popup_ = nullptr;
+      break;
+    }
+    case WebInputEvent::Type::kGestureTwoFingerTap:
+    case WebInputEvent::Type::kGestureLongPress:
+    case WebInputEvent::Type::kGestureLongTap:
+      if (scaled_event.GetType() == WebInputEvent::Type::kGestureLongTap) {
+        if (LocalFrame* inner_frame =
+                targeted_event.GetHitTestResult().InnerNodeFrame()) {
+          if (!inner_frame->GetEventHandler().LongTapShouldInvokeContextMenu())
+            break;
+        } else if (!frame->GetEventHandler().LongTapShouldInvokeContextMenu()) {
+          break;
+        }
+      }
+
+      GetPage()->GetContextMenuController().ClearContextMenu();
+      {
+        ContextMenuAllowedScope scope;
+        event_result =
+            frame->GetEventHandler().HandleGestureEvent(targeted_event);
+      }
+
+      break;
+    case WebInputEvent::Type::kGestureTapDown:
+      // Touch pinch zoom and scroll on the page (outside of a popup) must hide
+      // the popup. In case of a touch scroll or pinch zoom, this function is
+      // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
+      // When we close a popup because of a GestureTapDown, we also save it so
+      // we can prevent the following GestureTap from immediately reopening the
+      // same popup.
+      // This value should not persist outside of a gesture, so is cleared by
+      // GestureTap (where it is used) and by GestureCancel.
+      last_hidden_page_popup_ = web_view->GetPagePopup();
+      web_view->CancelPagePopup();
+      event_result =
+          frame->GetEventHandler().HandleGestureEvent(targeted_event);
+      break;
+    case WebInputEvent::Type::kGestureTapCancel:
+      // Don't have this value persist outside of a single tap gesture.
+      last_hidden_page_popup_ = nullptr;
+      event_result =
+          frame->GetEventHandler().HandleGestureEvent(targeted_event);
+      break;
+    case WebInputEvent::Type::kGestureShowPress:
+    case WebInputEvent::Type::kGestureTapUnconfirmed:
+      event_result =
+          frame->GetEventHandler().HandleGestureEvent(targeted_event);
+      break;
+    default:
+      NOTREACHED();
+  }
+  DidHandleGestureEvent(event);
+  return event_result;
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleMouseWheel(
+    LocalFrame& frame,
+    const WebMouseWheelEvent& event) {
+  View()->CancelPagePopup();
+  return PageWidgetEventHandler::HandleMouseWheel(frame, event);
+  // PageWidgetEventHandler may have detached the frame.
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleCharEvent(
+    const WebKeyboardEvent& event) {
+  DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
+
+  // Please refer to the comments explaining the m_suppressNextKeypressEvent
+  // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
+  // handled by Webkit. A keyDown event is typically associated with a
+  // keyPress(char) event and a keyUp event. We reset this flag here as it
+  // only applies to the current keyPress event.
+  bool suppress = suppress_next_keypress_event_;
+  suppress_next_keypress_event_ = false;
+
+  // If there is a popup open, it should be the one processing the event,
+  // not the page.
+  scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
+  if (page_popup)
+    return page_popup->HandleKeyEvent(event);
+
+  LocalFrame* frame = To<LocalFrame>(FocusedCoreFrame());
+  if (!frame) {
+    return suppress ? WebInputEventResult::kHandledSuppressed
+                    : WebInputEventResult::kNotHandled;
+  }
+
+  EventHandler& handler = frame->GetEventHandler();
+
+  if (!event.IsCharacterKey())
+    return WebInputEventResult::kHandledSuppressed;
+
+  // Accesskeys are triggered by char events and can't be suppressed.
+  // It is unclear whether a keypress should be dispatched as well
+  // crbug.com/563507
+  if (handler.HandleAccessKey(event))
+    return WebInputEventResult::kHandledSystem;
+
+  // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
+  // the eventHandler::keyEvent. We mimic this behavior on all platforms since
+  // for now we are converting other platform's key events to windows key
+  // events.
+  if (event.is_system_key)
+    return WebInputEventResult::kNotHandled;
+
+  if (suppress)
+    return WebInputEventResult::kHandledSuppressed;
+
+  WebInputEventResult result = handler.KeyEvent(event);
+  if (result != WebInputEventResult::kNotHandled)
+    return result;
+
+  return WebInputEventResult::kNotHandled;
+}
+
+void WebFrameWidgetImpl::CancelDrag() {
+  // It's possible for this to be called while we're not doing a drag if
+  // it's from a previous page that got unloaded.
+  if (!doing_drag_and_drop_)
+    return;
+  GetPage()->GetDragController().DragEnded();
+  doing_drag_and_drop_ = false;
+}
+
+void WebFrameWidgetImpl::StartDragging(const WebDragData& drag_data,
+                                       DragOperationsMask operations_allowed,
+                                       const SkBitmap& drag_image,
+                                       const gfx::Point& drag_image_offset) {
+  doing_drag_and_drop_ = true;
+  if (Client()->InterceptStartDragging(drag_data, operations_allowed,
+                                       drag_image, drag_image_offset)) {
+    return;
+  }
+
+  gfx::Point offset_in_dips =
+      widget_base_->BlinkSpaceToFlooredDIPs(drag_image_offset);
+  GetAssociatedFrameWidgetHost()->StartDragging(
+      drag_data, operations_allowed, drag_image,
+      gfx::Vector2d(offset_in_dips.x(), offset_in_dips.y()),
+      possible_drag_event_info_.Clone());
+}
+
+DragOperation WebFrameWidgetImpl::DragTargetDragEnterOrOver(
+    const gfx::PointF& point_in_viewport,
+    const gfx::PointF& screen_point,
+    DragAction drag_action,
+    uint32_t key_modifiers) {
+  DCHECK(current_drag_data_);
+  // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be
+  // null here, but this is somehow happening (rarely). This suggests that in
+  // some cases drag-over is happening before drag-enter, which should be
+  // impossible. This needs to be investigated further. Once fixed, the extra
+  // check for |!m_currentDragData| should be removed. (crbug.com/671504)
+  if (IgnoreInputEvents() || !current_drag_data_) {
+    CancelDrag();
+    return kDragOperationNone;
+  }
+
+  FloatPoint point_in_root_frame(ViewportToRootFrame(point_in_viewport));
+
+  current_drag_data_->SetModifiers(key_modifiers);
+  DragData drag_data(current_drag_data_.Get(), FloatPoint(point_in_root_frame),
+                     FloatPoint(screen_point), operations_allowed_);
+
+  DragOperation drag_operation =
+      GetPage()->GetDragController().DragEnteredOrUpdated(
+          &drag_data, *local_root_->GetFrame());
+
+  // Mask the drag operation against the drag source's allowed
+  // operations.
+  if (!(drag_operation & drag_data.DraggingSourceOperationMask()))
+    drag_operation = kDragOperationNone;
+
+  drag_operation_ = drag_operation;
+
+  return drag_operation_;
+}
+
+void WebFrameWidgetImpl::SendOverscrollEventFromImplSide(
+    const gfx::Vector2dF& overscroll_delta,
+    cc::ElementId scroll_latched_element_id) {
+  if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
+    return;
+
+  Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
+      scroll_latched_element_id);
+  if (target_node) {
+    target_node->GetDocument().EnqueueOverscrollEventForNode(
+        target_node, overscroll_delta.x(), overscroll_delta.y());
+  }
+}
+
+void WebFrameWidgetImpl::SendScrollEndEventFromImplSide(
+    cc::ElementId scroll_latched_element_id) {
+  if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
+    return;
+
+  Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
+      scroll_latched_element_id);
+  if (target_node)
+    target_node->GetDocument().EnqueueScrollEndEventForNode(target_node);
+}
+
+WebInputMethodController*
+WebFrameWidgetImpl::GetActiveWebInputMethodController() const {
+  WebLocalFrameImpl* local_frame =
+      WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
+  return local_frame ? local_frame->GetInputMethodController() : nullptr;
+}
+
+gfx::PointF WebFrameWidgetImpl::ViewportToRootFrame(
+    const gfx::PointF& point_in_viewport) const {
+  return GetPage()->GetVisualViewport().ViewportToRootFrame(
+      FloatPoint(point_in_viewport));
+}
+
+WebViewImpl* WebFrameWidgetImpl::View() const {
+  return local_root_->ViewImpl();
+}
+
+Page* WebFrameWidgetImpl::GetPage() const {
+  return View()->GetPage();
+}
+
+mojom::blink::FrameWidgetHost*
+WebFrameWidgetImpl::GetAssociatedFrameWidgetHost() const {
+  return frame_widget_host_.get();
+}
+
+void WebFrameWidgetImpl::RequestDecode(
+    const PaintImage& image,
+    base::OnceCallback<void(bool)> callback) {
+  widget_base_->LayerTreeHost()->QueueImageDecode(image, std::move(callback));
+
+  // In web tests the request does not actually cause a commit, because the
+  // compositor is scheduled by the test runner to avoid flakiness. So for this
+  // case we must request a main frame.
+  Client()->ScheduleAnimationForWebTests();
+}
+
+void WebFrameWidgetImpl::Trace(Visitor* visitor) const {
+  visitor->Trace(local_root_);
+  visitor->Trace(current_drag_data_);
+  visitor->Trace(frame_widget_host_);
+  visitor->Trace(receiver_);
+  visitor->Trace(input_target_receiver_);
+  visitor->Trace(mouse_capture_element_);
+  visitor->Trace(device_emulator_);
+}
+
+void WebFrameWidgetImpl::SetNeedsRecalculateRasterScales() {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->SetNeedsRecalculateRasterScales();
+}
+
+void WebFrameWidgetImpl::SetBackgroundColor(SkColor color) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->set_background_color(color);
+}
+
+void WebFrameWidgetImpl::SetOverscrollBehavior(
+    const cc::OverscrollBehavior& overscroll_behavior) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->SetOverscrollBehavior(overscroll_behavior);
+}
+
+void WebFrameWidgetImpl::RegisterSelection(cc::LayerSelection selection) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->RegisterSelection(selection);
+}
+
+void WebFrameWidgetImpl::StartPageScaleAnimation(
+    const gfx::Vector2d& destination,
+    bool use_anchor,
+    float new_page_scale,
+    base::TimeDelta duration) {
+  widget_base_->LayerTreeHost()->StartPageScaleAnimation(
+      destination, use_anchor, new_page_scale, duration);
+}
+
+void WebFrameWidgetImpl::RequestBeginMainFrameNotExpected(bool request) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->RequestBeginMainFrameNotExpected(request);
+}
+
+void WebFrameWidgetImpl::DidCommitAndDrawCompositorFrame() {
+  ForEachLocalFrameControlledByWidget(
+      local_root_->GetFrame(),
+      WTF::BindRepeating([](WebLocalFrame* local_frame) {
+        local_frame->Client()->DidCommitAndDrawCompositorFrame();
+      }));
+}
+
+void WebFrameWidgetImpl::DidObserveFirstScrollDelay(
+    base::TimeDelta first_scroll_delay,
+    base::TimeTicks first_scroll_timestamp) {
+  if (!local_root_ || !(local_root_->GetFrame()) ||
+      !(local_root_->GetFrame()->GetDocument())) {
+    return;
+  }
+  InteractiveDetector* interactive_detector =
+      InteractiveDetector::From(*(local_root_->GetFrame()->GetDocument()));
+  if (interactive_detector) {
+    interactive_detector->DidObserveFirstScrollDelay(first_scroll_delay,
+                                                     first_scroll_timestamp);
+  }
+}
+
+std::unique_ptr<cc::LayerTreeFrameSink>
+WebFrameWidgetImpl::AllocateNewLayerTreeFrameSink() {
+  return Client()->AllocateNewLayerTreeFrameSink();
+}
+
+void WebFrameWidgetImpl::DidBeginMainFrame() {
+  Client()->DidBeginMainFrame();
+  DCHECK(LocalRootImpl()->GetFrame());
+  PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame());
+}
+
+void WebFrameWidgetImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
+                                         DocumentUpdateReason reason) {
+  TRACE_EVENT0("blink", "WebFrameWidgetImpl::UpdateLifecycle");
+  if (!LocalRootImpl())
+    return;
+
+  PageWidgetDelegate::UpdateLifecycle(*GetPage(), *LocalRootImpl()->GetFrame(),
+                                      requested_update, reason);
+  if (requested_update != WebLifecycleUpdate::kAll)
+    return;
+
+  View()->UpdatePagePopup();
+
+  // Meaningful layout events and background colors only apply to main frames.
+  if (ForMainFrame()) {
+    MainFrameData& data = main_data();
+
+    // There is no background color for non-composited WebViews (eg
+    // printing).
+    if (View()->does_composite()) {
+      SkColor background_color = View()->BackgroundColor();
+      SetBackgroundColor(background_color);
+      if (background_color != data.last_background_color) {
+        LocalRootImpl()->GetFrame()->DidChangeBackgroundColor(
+            background_color, false /* color_adjust */);
+        data.last_background_color = background_color;
+      }
+    }
+
+    if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
+      LocalFrame* frame = LocalRootImpl()->GetFrame();
+
+      if (data.should_dispatch_first_visually_non_empty_layout &&
+          view->IsVisuallyNonEmpty()) {
+        data.should_dispatch_first_visually_non_empty_layout = false;
+        // TODO(esprehn): Move users of this callback to something
+        // better, the heuristic for "visually non-empty" is bad.
+        DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
+      }
+
+      if (data.should_dispatch_first_layout_after_finished_parsing &&
+          frame->GetDocument()->HasFinishedParsing()) {
+        data.should_dispatch_first_layout_after_finished_parsing = false;
+        DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
+      }
+
+      if (data.should_dispatch_first_layout_after_finished_loading &&
+          frame->GetDocument()->IsLoadCompleted()) {
+        data.should_dispatch_first_layout_after_finished_loading = false;
+        DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
+      }
+    }
+  }
+}
+
+void WebFrameWidgetImpl::WillBeginMainFrame() {
+  Client()->WillBeginMainFrame();
+}
+
+void WebFrameWidgetImpl::DidCompletePageScaleAnimation() {
+  // Page scale animations only happen on the main frame.
+  DCHECK(ForMainFrame());
+  if (auto* focused_frame = View()->FocusedFrame()) {
+    if (focused_frame->AutofillClient())
+      focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
+  }
+}
+
+void WebFrameWidgetImpl::ScheduleAnimation() {
+  Client()->ScheduleAnimation();
+}
+
+void WebFrameWidgetImpl::FocusChanged(bool enable) {
+  // TODO(crbug.com/689777): FocusChange events are only sent to the MainFrame
+  // these maybe should goto the local root so that the rest of input messages
+  // sent to those are preserved in order.
+  DCHECK(ForMainFrame());
+  View()->SetPageFocus(enable);
+}
+
+bool WebFrameWidgetImpl::ShouldAckSyntheticInputImmediately() {
+  // TODO(bokan): The RequestPresentation API appears not to function in VR. As
+  // a short term workaround for https://crbug.com/940063, ACK input
+  // immediately rather than using RequestPresentation.
+  if (GetPage()->GetSettings().GetImmersiveModeEnabled())
+    return true;
+  return false;
+}
+
+void WebFrameWidgetImpl::UpdateVisualProperties(
+    const VisualProperties& visual_properties) {
+  SetZoomLevel(visual_properties.zoom_level);
+
+  // TODO(danakj): In order to synchronize updates between local roots, the
+  // display mode should be propagated to RenderFrameProxies and down through
+  // their RenderWidgetHosts to child WebFrameWidgetImpl via the
+  // VisualProperties waterfall, instead of coming to each WebFrameWidgetImpl
+  // independently.
+  // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode
+  SetDisplayMode(visual_properties.display_mode);
+
+  if (ForMainFrame()) {
+    SetAutoResizeMode(visual_properties.auto_resize_enabled,
+                      visual_properties.min_size_for_auto_resize,
+                      visual_properties.max_size_for_auto_resize,
+                      visual_properties.screen_info.device_scale_factor);
+  }
+
+  bool capture_sequence_number_changed =
+      visual_properties.capture_sequence_number !=
+      last_capture_sequence_number_;
+  if (capture_sequence_number_changed) {
+    last_capture_sequence_number_ = visual_properties.capture_sequence_number;
+
+    // Send the capture sequence number to RemoteFrames that are below the
+    // local root for this widget.
+    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+        [](uint32_t capture_sequence_number, RemoteFrame* remote_frame) {
+          remote_frame->Client()->UpdateCaptureSequenceNumber(
+              capture_sequence_number);
+        },
+        visual_properties.capture_sequence_number));
+  }
+
+  if (!View()->AutoResizeMode()) {
+    if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_) {
+      is_fullscreen_granted_ = visual_properties.is_fullscreen_granted;
+      if (is_fullscreen_granted_)
+        View()->DidEnterFullscreen();
+      else
+        View()->DidExitFullscreen();
+    }
+  }
+
+  gfx::Size old_visible_viewport_size_in_dips =
+      widget_base_->VisibleViewportSizeInDIPs();
+  ApplyVisualPropertiesSizing(visual_properties);
+
+  if (old_visible_viewport_size_in_dips !=
+      widget_base_->VisibleViewportSizeInDIPs()) {
+    ForEachLocalFrameControlledByWidget(
+        local_root_->GetFrame(),
+        WTF::BindRepeating([](WebLocalFrame* local_frame) {
+          local_frame->Client()->ResetHasScrolledFocusedEditableIntoView();
+        }));
+
+    // Propagate changes down to child local root RenderWidgets and
+    // BrowserPlugins in other frame trees/processes.
+    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+        [](const gfx::Size& visible_viewport_size, RemoteFrame* remote_frame) {
+          remote_frame->Client()->DidChangeVisibleViewportSize(
+              visible_viewport_size);
+        },
+        widget_base_->VisibleViewportSizeInDIPs()));
+  }
+
+  // All non-top-level Widgets (child local-root frames, Portals, GuestViews,
+  // etc.) propagate and consume the page scale factor as "external", meaning
+  // that it comes from the top level widget's page scale.
+  if (!ForTopMostMainFrame()) {
+    // The main frame controls the page scale factor, from blink. For other
+    // frame widgets, the page scale is received from its parent as part of
+    // the visual properties here. While blink doesn't need to know this
+    // page scale factor outside the main frame, the compositor does in
+    // order to produce its output at the correct scale.
+    widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
+        visual_properties.page_scale_factor,
+        visual_properties.is_pinch_gesture_active);
+
+    NotifyPageScaleFactorChanged(visual_properties.page_scale_factor,
+                                 visual_properties.is_pinch_gesture_active);
+  } else {
+    // Ensure the external scale factor in top-level widgets is reset as it may
+    // be leftover from when a widget was nested and was promoted to top level
+    // (e.g. portal activation).
+    widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
+        1.f,
+        /*is_pinch_gesture_active=*/false);
+  }
+
+  // TODO(crbug.com/939118): ScrollFocusedNodeIntoViewForWidget does not work
+  // when the focused node is inside an OOPIF. This code path where
+  // scroll_focused_node_into_view is set is used only for WebView, crbug
+  // 939118 tracks fixing webviews to not use scroll_focused_node_into_view.
+  if (visual_properties.scroll_focused_node_into_view)
+    ScrollFocusedEditableElementIntoView();
+}
+
+void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
+    const VisualProperties& visual_properties) {
+  gfx::Rect new_compositor_viewport_pixel_rect =
+      visual_properties.compositor_viewport_pixel_rect;
+  if (ForMainFrame()) {
+    if (size_ !=
+        widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size)) {
+      // Only hide popups when the size changes. Eg https://crbug.com/761908.
+      View()->CancelPagePopup();
+    }
+
+    if (auto* device_emulator = DeviceEmulator()) {
+      device_emulator->UpdateVisualProperties(visual_properties);
+      return;
+    }
+
+    if (AutoResizeMode()) {
+      new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize(
+          widget_base_->BlinkSpaceToFlooredDIPs(size_.value_or(gfx::Size())),
+          visual_properties.screen_info.device_scale_factor));
+    }
+  }
+
+  SetWindowSegments(visual_properties.root_widget_window_segments);
+
+  widget_base_->UpdateSurfaceAndScreenInfo(
+      visual_properties.local_surface_id.value_or(viz::LocalSurfaceId()),
+      new_compositor_viewport_pixel_rect, visual_properties.screen_info);
+
+  // Store this even when auto-resizing, it is the size of the full viewport
+  // used for clipping, and this value is propagated down the Widget
+  // hierarchy via the VisualProperties waterfall.
+  widget_base_->SetVisibleViewportSizeInDIPs(
+      visual_properties.visible_viewport_size);
+
+  if (ForMainFrame()) {
+    if (!AutoResizeMode()) {
+      size_ = widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size);
+
+      View()->ResizeWithBrowserControls(
+          size_.value(),
+          widget_base_->DIPsToCeiledBlinkSpace(
+              widget_base_->VisibleViewportSizeInDIPs()),
+          visual_properties.browser_controls_params);
+    }
+  } else {
+    // Widgets in a WebView's frame tree without a local main frame
+    // set the size of the WebView to be the |visible_viewport_size|, in order
+    // to limit compositing in (out of process) child frames to what is visible.
+    //
+    // Note that child frames in the same process/WebView frame tree as the
+    // main frame do not do this in order to not clobber the source of truth in
+    // the main frame.
+    if (!View()->MainFrameImpl()) {
+      View()->Resize(widget_base_->DIPsToCeiledBlinkSpace(
+          widget_base_->VisibleViewportSizeInDIPs()));
+    }
+
+    Resize(widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size));
+  }
+}
+
+void WebFrameWidgetImpl::ScheduleAnimationForWebTests() {
+  Client()->ScheduleAnimationForWebTests();
+}
+
+int WebFrameWidgetImpl::GetLayerTreeId() {
+  if (!View()->does_composite())
+    return 0;
+  return widget_base_->LayerTreeHost()->GetId();
+}
+
+void WebFrameWidgetImpl::SetHaveScrollEventHandlers(bool has_handlers) {
+  widget_base_->LayerTreeHost()->SetHaveScrollEventHandlers(has_handlers);
+}
+
+void WebFrameWidgetImpl::SetEventListenerProperties(
+    cc::EventListenerClass listener_class,
+    cc::EventListenerProperties listener_properties) {
+  widget_base_->LayerTreeHost()->SetEventListenerProperties(
+      listener_class, listener_properties);
+
+  if (listener_class == cc::EventListenerClass::kTouchStartOrMove ||
+      listener_class == cc::EventListenerClass::kTouchEndOrCancel) {
+    bool has_touch_handlers =
+        EventListenerProperties(cc::EventListenerClass::kTouchStartOrMove) !=
+            cc::EventListenerProperties::kNone ||
+        EventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel) !=
+            cc::EventListenerProperties::kNone;
+    if (!has_touch_handlers_ || *has_touch_handlers_ != has_touch_handlers) {
+      has_touch_handlers_ = has_touch_handlers;
+
+      // Can be null when running tests.
+      if (auto* scheduler_state = widget_base_->RendererWidgetSchedulingState())
+        scheduler_state->SetHasTouchHandler(has_touch_handlers);
+      // Set touch event consumers based on whether there are touch event
+      // handlers or the page has hit testable scrollbars.
+      auto touch_event_consumers = mojom::blink::TouchEventConsumers::New(
+          has_touch_handlers, GetPage()->GetScrollbarTheme().AllowsHitTest());
+      frame_widget_host_->SetHasTouchEventConsumers(
+          std::move(touch_event_consumers));
+    }
+  } else if (listener_class == cc::EventListenerClass::kPointerRawUpdate) {
+    SetHasPointerRawUpdateEventHandlers(listener_properties !=
+                                        cc::EventListenerProperties::kNone);
+  }
+}
+
+cc::EventListenerProperties WebFrameWidgetImpl::EventListenerProperties(
+    cc::EventListenerClass listener_class) const {
+  return widget_base_->LayerTreeHost()->event_listener_properties(
+      listener_class);
+}
+
+mojom::blink::DisplayMode WebFrameWidgetImpl::DisplayMode() const {
+  return display_mode_;
+}
+
+const WebVector<gfx::Rect>& WebFrameWidgetImpl::WindowSegments() const {
+  return window_segments_;
+}
+
+void WebFrameWidgetImpl::StartDeferringCommits(base::TimeDelta timeout) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->StartDeferringCommits(timeout);
+}
+
+void WebFrameWidgetImpl::StopDeferringCommits(
+    cc::PaintHoldingCommitTrigger triggger) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->StopDeferringCommits(triggger);
+}
+
+std::unique_ptr<cc::ScopedDeferMainFrameUpdate>
+WebFrameWidgetImpl::DeferMainFrameUpdate() {
+  return widget_base_->LayerTreeHost()->DeferMainFrameUpdate();
+}
+
+void WebFrameWidgetImpl::SetBrowserControlsShownRatio(float top_ratio,
+                                                      float bottom_ratio) {
+  widget_base_->LayerTreeHost()->SetBrowserControlsShownRatio(top_ratio,
+                                                              bottom_ratio);
+}
+
+void WebFrameWidgetImpl::SetBrowserControlsParams(
+    cc::BrowserControlsParams params) {
+  widget_base_->LayerTreeHost()->SetBrowserControlsParams(params);
+}
+
+cc::LayerTreeDebugState WebFrameWidgetImpl::GetLayerTreeDebugState() {
+  return widget_base_->LayerTreeHost()->GetDebugState();
+}
+
+void WebFrameWidgetImpl::SetLayerTreeDebugState(
+    const cc::LayerTreeDebugState& state) {
+  widget_base_->LayerTreeHost()->SetDebugState(state);
+}
+
+void WebFrameWidgetImpl::SynchronouslyCompositeForTesting(
+    base::TimeTicks frame_time) {
+  widget_base_->LayerTreeHost()->CompositeForTest(frame_time, false);
+}
+
+void WebFrameWidgetImpl::UseSynchronousResizeModeForTesting(bool enable) {
+  main_data().synchronous_resize_mode_for_testing = enable;
+}
+
+void WebFrameWidgetImpl::SetDeviceColorSpaceForTesting(
+    const gfx::ColorSpace& color_space) {
+  DCHECK(ForMainFrame());
+  // We are changing the device color space from the renderer, so allocate a
+  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+  blink::ScreenInfo info = widget_base_->GetScreenInfo();
+  info.display_color_spaces = gfx::DisplayColorSpaces(color_space);
+  widget_base_->UpdateScreenInfo(info);
+}
+
+// TODO(665924): Remove direct dispatches of mouse events from
+// PointerLockController, instead passing them through EventHandler.
+void WebFrameWidgetImpl::PointerLockMouseEvent(
+    const WebCoalescedInputEvent& coalesced_event) {
+  const WebInputEvent& input_event = coalesced_event.Event();
+  const WebMouseEvent& mouse_event =
+      static_cast<const WebMouseEvent&>(input_event);
+  WebMouseEvent transformed_event =
+      TransformWebMouseEvent(local_root_->GetFrameView(), mouse_event);
+
+  AtomicString event_type;
+  switch (input_event.GetType()) {
+    case WebInputEvent::Type::kMouseDown:
+      event_type = event_type_names::kMousedown;
+      if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
+        break;
+      LocalFrame::NotifyUserActivation(
+          GetPage()
+              ->GetPointerLockController()
+              .GetElement()
+              ->GetDocument()
+              .GetFrame(),
+          mojom::blink::UserActivationNotificationType::kInteraction);
+      break;
+    case WebInputEvent::Type::kMouseUp:
+      event_type = event_type_names::kMouseup;
+      break;
+    case WebInputEvent::Type::kMouseMove:
+      event_type = event_type_names::kMousemove;
+      break;
+    default:
+      NOTREACHED() << input_event.GetType();
+  }
+
+  if (GetPage()) {
+    GetPage()->GetPointerLockController().DispatchLockedMouseEvent(
+        transformed_event,
+        TransformWebMouseEventVector(
+            local_root_->GetFrameView(),
+            coalesced_event.GetCoalescedEventsPointers()),
+        TransformWebMouseEventVector(
+            local_root_->GetFrameView(),
+            coalesced_event.GetPredictedEventsPointers()),
+        event_type);
+  }
+}
+bool WebFrameWidgetImpl::IsPointerLocked() {
+  if (GetPage()) {
+    return GetPage()->GetPointerLockController().IsPointerLocked();
+  }
+  return false;
+}
+
+void WebFrameWidgetImpl::ShowContextMenu(
+    ui::mojom::blink::MenuSourceType source_type,
+    const gfx::Point& location) {
+  host_context_menu_location_ = location;
+
+  if (!GetPage())
+    return;
+  GetPage()->GetContextMenuController().ClearContextMenu();
+  {
+    ContextMenuAllowedScope scope;
+    if (LocalFrame* focused_frame =
+            GetPage()->GetFocusController().FocusedFrame()) {
+      focused_frame->GetEventHandler().ShowNonLocatedContextMenu(
+          nullptr, static_cast<blink::WebMenuSourceType>(source_type));
+    }
+  }
+  host_context_menu_location_.reset();
+}
+
+void WebFrameWidgetImpl::SetViewportIntersection(
+    mojom::blink::ViewportIntersectionStatePtr intersection_state) {
+  // Remote viewports are only applicable to local frames with remote ancestors.
+  // TODO(https://crbug.com/1148960): Should this deal with portals?
+  DCHECK(ForSubframe());
+
+  child_data().compositor_visible_rect =
+      intersection_state->compositor_visible_rect;
+  widget_base_->LayerTreeHost()->SetViewportVisibleRect(
+      intersection_state->compositor_visible_rect);
+  LocalRootImpl()->GetFrame()->SetViewportIntersectionFromParent(
+      *intersection_state);
+}
+
+void WebFrameWidgetImpl::EnableDeviceEmulation(
+    const DeviceEmulationParams& parameters) {
+  // Device Emaulation is only supported for the main frame.
+  DCHECK(ForMainFrame());
+  if (!device_emulator_) {
+    gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
+
+    device_emulator_ = MakeGarbageCollected<ScreenMetricsEmulator>(
+        this, widget_base_->GetScreenInfo(), size_in_dips,
+        widget_base_->VisibleViewportSizeInDIPs(),
+        widget_base_->WidgetScreenRect(), widget_base_->WindowScreenRect());
+  }
+  device_emulator_->ChangeEmulationParams(parameters);
+}
+
+void WebFrameWidgetImpl::DisableDeviceEmulation() {
+  if (!device_emulator_)
+    return;
+  device_emulator_->DisableAndApply();
+  device_emulator_ = nullptr;
+}
+
+void WebFrameWidgetImpl::SetIsInertForSubFrame(bool inert) {
+  DCHECK(ForSubframe());
+  LocalRootImpl()->GetFrame()->SetIsInert(inert);
+}
+
+base::Optional<gfx::Point>
+WebFrameWidgetImpl::GetAndResetContextMenuLocation() {
+  return std::move(host_context_menu_location_);
+}
+
+void WebFrameWidgetImpl::SetZoomLevel(double zoom_level) {
+  // Override the zoom level with the testing one if necessary.
+  if (zoom_level_for_testing_ != -INFINITY)
+    zoom_level = zoom_level_for_testing_;
+
+  View()->SetZoomLevel(zoom_level);
+
+  // Part of the UpdateVisualProperties dance we send the zoom level to
+  // RemoteFrames that are below the local root for this widget.
+  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+      [](double zoom_level, RemoteFrame* remote_frame) {
+        remote_frame->Client()->ZoomLevelChanged(zoom_level);
+      },
+      zoom_level));
+}
+
+void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize,
+                                           const gfx::Size& min_window_size,
+                                           const gfx::Size& max_window_size,
+                                           float device_scale_factor) {
+  // Auto resize only applies to main frames.
+  DCHECK(ForMainFrame());
+
+  if (auto_resize) {
+    if (!Platform::Current()->IsUseZoomForDSFEnabled())
+      device_scale_factor = 1.f;
+    View()->EnableAutoResizeMode(
+        gfx::ScaleToCeiledSize(min_window_size, device_scale_factor),
+        gfx::ScaleToCeiledSize(max_window_size, device_scale_factor));
+  } else if (AutoResizeMode()) {
+    View()->DisableAutoResizeMode();
+  }
+}
+
+void WebFrameWidgetImpl::DidAutoResize(const gfx::Size& size) {
+  DCHECK(ForMainFrame());
+  gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(size);
+  size_ = size;
+
+  if (main_data().synchronous_resize_mode_for_testing) {
+    gfx::Rect new_pos(widget_base_->WindowRect());
+    new_pos.set_size(size_in_dips);
+    SetScreenRects(new_pos, new_pos);
+  }
+
+  // TODO(ccameron): Note that this destroys any information differentiating
+  // |size| from the compositor's viewport size.
+  gfx::Rect size_with_dsf = gfx::Rect(gfx::ScaleToCeiledSize(
+      gfx::Rect(size_in_dips).size(),
+      widget_base_->GetScreenInfo().device_scale_factor));
+  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+  widget_base_->UpdateCompositorViewportRect(size_with_dsf);
+}
+
+LocalFrame* WebFrameWidgetImpl::FocusedLocalFrameInWidget() const {
+  if (!local_root_) {
+    // WebFrameWidget is created in the call to CreateFrame. The corresponding
+    // RenderWidget, however, might not swap in right away (InstallNewDocument()
+    // will lead to it swapping in). During this interval local_root_ is nullptr
+    // (see https://crbug.com/792345).
+    return nullptr;
+  }
+
+  LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
+  return (frame && frame->LocalFrameRoot() == local_root_->GetFrame())
+             ? frame
+             : nullptr;
+}
+
+WebLocalFrame* WebFrameWidgetImpl::FocusedWebLocalFrameInWidget() const {
+  return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
+}
+
+bool WebFrameWidgetImpl::ScrollFocusedEditableElementIntoView() {
+  Element* element = FocusedElement();
+  if (!element || !WebElement(element).IsEditable())
+    return false;
+
+  element->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
+
+  if (!element->GetLayoutObject())
+    return false;
+
+  PhysicalRect rect_to_scroll;
+  auto params =
+      GetScrollParamsForFocusedEditableElement(*element, rect_to_scroll);
+  element->GetLayoutObject()->ScrollRectToVisible(rect_to_scroll,
+                                                  std::move(params));
+
+  // Second phase for main frames is to schedule a zoom animation.
+  if (ForMainFrame()) {
+    LocalFrameView* main_frame_view = LocalRootImpl()->GetFrame()->View();
+
+    View()->ZoomAndScrollToFocusedEditableElementRect(
+        main_frame_view->RootFrameToDocument(
+            element->GetDocument().View()->ConvertToRootFrame(
+                element->GetLayoutObject()->AbsoluteBoundingBoxRect())),
+        main_frame_view->RootFrameToDocument(
+            element->GetDocument().View()->ConvertToRootFrame(
+                element->GetDocument()
+                    .GetFrame()
+                    ->Selection()
+                    .ComputeRectToScroll(kDoNotRevealExtent))),
+        View()->ShouldZoomToLegibleScale(*element));
+  }
+
+  return true;
+}
+
+void WebFrameWidgetImpl::ResetMeaningfulLayoutStateForMainFrame() {
+  MainFrameData& data = main_data();
+  data.should_dispatch_first_visually_non_empty_layout = true;
+  data.should_dispatch_first_layout_after_finished_parsing = true;
+  data.should_dispatch_first_layout_after_finished_loading = true;
+}
+
+cc::LayerTreeHost* WebFrameWidgetImpl::InitializeCompositing(
+    scheduler::WebThreadScheduler* main_thread_scheduler,
+    cc::TaskGraphRunner* task_graph_runner,
+    const ScreenInfo& screen_info,
+    std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
+    const cc::LayerTreeSettings* settings) {
+  widget_base_->InitializeCompositing(
+      main_thread_scheduler, task_graph_runner, is_for_child_local_root_,
+      screen_info, std::move(ukm_recorder_factory), settings);
+
+  LocalFrameView* frame_view;
+  if (is_for_child_local_root_) {
+    frame_view = LocalRootImpl()->GetFrame()->View();
+  } else {
+    // Scrolling for the root frame is special we need to pass null indicating
+    // we are at the top of the tree when setting up the Animation. Which will
+    // cause ownership of the timeline and animation host.
+    // See ScrollingCoordinator::AnimationHostInitialized.
+    frame_view = nullptr;
+  }
+
+  GetPage()->AnimationHostInitialized(*AnimationHost(), frame_view);
+  return widget_base_->LayerTreeHost();
+}
+
+void WebFrameWidgetImpl::SetCompositorVisible(bool visible) {
+  widget_base_->SetCompositorVisible(visible);
+}
+
+gfx::Size WebFrameWidgetImpl::Size() {
+  return size_.value_or(gfx::Size());
+}
+
+void WebFrameWidgetImpl::Resize(const gfx::Size& new_size) {
+  if (size_ && *size_ == new_size)
+    return;
+
+  if (ForMainFrame()) {
+    size_ = new_size;
+    View()->Resize(new_size);
+    return;
+  }
+
+  if (child_data().did_suspend_parsing) {
+    child_data().did_suspend_parsing = false;
+    LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->ResumeParser();
+  }
+
+  LocalFrameView* view = LocalRootImpl()->GetFrameView();
+  DCHECK(view);
+
+  size_ = new_size;
+
+  view->SetLayoutSize(IntSize(*size_));
+  view->Resize(IntSize(*size_));
+
+  // FIXME: In WebViewImpl this layout was a precursor to setting the minimum
+  // scale limit.  It is not clear if this is necessary for frame-level widget
+  // resize.
+  if (view->NeedsLayout())
+    view->UpdateLayout();
+
+  // FIXME: Investigate whether this is needed; comment from eseidel suggests
+  // that this function is flawed.
+  // TODO(kenrb): It would probably make more sense to check whether lifecycle
+  // updates are throttled in the root's LocalFrameView, but for OOPIFs that
+  // doesn't happen. Need to investigate if OOPIFs can be throttled during
+  // load.
+  if (LocalRootImpl()->GetFrame()->GetDocument()->IsLoadCompleted()) {
+    // FIXME: This is wrong. The LocalFrameView is responsible sending a
+    // resizeEvent as part of layout. Layout is also responsible for sending
+    // invalidations to the embedder. This method and all callers may be wrong.
+    // -- eseidel.
+    LocalRootImpl()->GetFrame()->GetDocument()->EnqueueResizeEvent();
+
+    // Pass the limits even though this is for subframes, as the limits will
+    // be needed in setting the raster scale. We set this value when setting
+    // up the compositor, but need to update it when the limits of the
+    // WebViewImpl have changed.
+    // TODO(wjmaclean): This is updating when the size of the *child frame*
+    // have changed which are completely independent of the WebView, and in an
+    // OOPIF where the main frame is remote, are these limits even useful?
+    SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
+                               View()->MinimumPageScaleFactor(),
+                               View()->MaximumPageScaleFactor());
+  }
+}
+
+void WebFrameWidgetImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
+  TRACE_EVENT1("blink", "WebFrameWidgetImpl::BeginMainFrame", "frameTime",
+               last_frame_time);
+  DCHECK(!last_frame_time.is_null());
+  CHECK(LocalRootImpl());
+
+  // Dirty bit on MouseEventManager is not cleared in OOPIFs after scroll
+  // or layout changes. Ensure the hover state is recomputed if necessary.
+  LocalRootImpl()
+      ->GetFrame()
+      ->GetEventHandler()
+      .RecomputeMouseHoverStateIfNeeded();
+
+  // Adjusting frame anchor only happens on the main frame.
+  if (ForMainFrame()) {
+    if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
+      if (FragmentAnchor* anchor = view->GetFragmentAnchor())
+        anchor->PerformPreRafActions();
+    }
+  }
+
+  base::Optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer;
+  if (WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
+    ukm_timer.emplace(LocalRootImpl()
+                          ->GetFrame()
+                          ->View()
+                          ->EnsureUkmAggregator()
+                          .GetScopedTimer(LocalFrameUkmAggregator::kAnimate));
+  }
+
+  PageWidgetDelegate::Animate(*GetPage(), last_frame_time);
+  // Animate can cause the local frame to detach.
+  if (!LocalRootImpl())
+    return;
+
+  GetPage()->GetValidationMessageClient().LayoutOverlay();
+}
+
+void WebFrameWidgetImpl::BeginCommitCompositorFrame() {
+  commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
+}
+
+void WebFrameWidgetImpl::EndCommitCompositorFrame(
+    base::TimeTicks commit_start_time) {
+  DCHECK(commit_compositor_frame_start_time_.has_value());
+  if (ForMainFrame()) {
+    View()->Client()->DidCommitCompositorFrameForLocalMainFrame(
+        commit_start_time);
+    View()->UpdatePreferredSize();
+    if (!View()->MainFrameImpl()) {
+      // Trying to track down why the view's idea of the main frame varies
+      // from LocalRootImpl's.
+      // TODO(https://crbug.com/1139104): Remove this.
+      std::string reason = View()->GetNullFrameReasonForBug1139104();
+      DCHECK(false) << reason;
+      SCOPED_CRASH_KEY_STRING32(Crbug1139104, NullFrameReason, reason);
+      base::debug::DumpWithoutCrashing();
+    }
+  }
+
+  LocalRootImpl()
+      ->GetFrame()
+      ->View()
+      ->EnsureUkmAggregator()
+      .RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
+                                  commit_start_time, base::TimeTicks::Now());
+  commit_compositor_frame_start_time_.reset();
+}
+
+void WebFrameWidgetImpl::ApplyViewportChanges(
+    const ApplyViewportChangesArgs& args) {
+  // Viewport changes only change the main frame.
+  if (!ForMainFrame())
+    return;
+  View()->ApplyViewportChanges(args);
+}
+
+void WebFrameWidgetImpl::RecordManipulationTypeCounts(
+    cc::ManipulationInfo info) {
+  // Manipulation counts are only recorded for the main frame.
+  if (!ForMainFrame())
+    return;
+  if ((info & cc::kManipulationInfoWheel) == cc::kManipulationInfoWheel) {
+    UseCounter::Count(LocalRootImpl()->GetDocument(),
+                      WebFeature::kScrollByWheel);
+  }
+  if ((info & cc::kManipulationInfoTouch) == cc::kManipulationInfoTouch) {
+    UseCounter::Count(LocalRootImpl()->GetDocument(),
+                      WebFeature::kScrollByTouch);
+  }
+  if ((info & cc::kManipulationInfoPinchZoom) ==
+      cc::kManipulationInfoPinchZoom) {
+    UseCounter::Count(LocalRootImpl()->GetDocument(), WebFeature::kPinchZoom);
+  }
+  if ((info & cc::kManipulationInfoPrecisionTouchPad) ==
+      cc::kManipulationInfoPrecisionTouchPad) {
+    UseCounter::Count(LocalRootImpl()->GetDocument(),
+                      WebFeature::kScrollByPrecisionTouchPad);
+  }
+}
+
+void WebFrameWidgetImpl::RecordDispatchRafAlignedInputTime(
+    base::TimeTicks raf_aligned_input_start_time) {
+  if (LocalRootImpl()) {
+    LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
+        LocalFrameUkmAggregator::kHandleInputEvents,
+        raf_aligned_input_start_time, base::TimeTicks::Now());
+  }
+}
+
+void WebFrameWidgetImpl::SetSuppressFrameRequestsWorkaroundFor704763Only(
+    bool suppress_frame_requests) {
+  GetPage()->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only(
+      suppress_frame_requests);
+}
+
+std::unique_ptr<cc::BeginMainFrameMetrics>
+WebFrameWidgetImpl::GetBeginMainFrameMetrics() {
+  if (!LocalRootImpl())
+    return nullptr;
+
+  return LocalRootImpl()
+      ->GetFrame()
+      ->View()
+      ->EnsureUkmAggregator()
+      .GetBeginMainFrameMetrics();
+}
+
+std::unique_ptr<cc::WebVitalMetrics> WebFrameWidgetImpl::GetWebVitalMetrics() {
+  if (!LocalRootImpl())
+    return nullptr;
+
+  // This class should be called at most once per commit.
+  WebPerformance perf = LocalRootImpl()->Performance();
+  auto metrics = std::make_unique<cc::WebVitalMetrics>();
+  if (perf.FirstInputDelay().has_value())
+    metrics->first_input_delay = *perf.FirstInputDelay();
+
+  base::TimeTicks start = perf.NavigationStartAsMonotonicTime();
+  base::TimeTicks largest_contentful_paint =
+      perf.LargestContentfulPaintAsMonotonicTime();
+  if (largest_contentful_paint >= start)
+    metrics->largest_contentful_paint = largest_contentful_paint - start;
+
+  double layout_shift = LocalRootImpl()
+                            ->GetFrame()
+                            ->View()
+                            ->GetLayoutShiftTracker()
+                            .WeightedScore();
+  if (layout_shift > 0.f)
+    metrics->layout_shift = layout_shift;
+  return metrics;
+}
+
+void WebFrameWidgetImpl::BeginUpdateLayers() {
+  if (LocalRootImpl())
+    update_layers_start_time_.emplace(base::TimeTicks::Now());
+}
+
+void WebFrameWidgetImpl::EndUpdateLayers() {
+  if (LocalRootImpl()) {
+    DCHECK(update_layers_start_time_);
+    LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
+        LocalFrameUkmAggregator::kUpdateLayers,
+        update_layers_start_time_.value(), base::TimeTicks::Now());
+    probe::LayerTreeDidChange(LocalRootImpl()->GetFrame());
+  }
+  update_layers_start_time_.reset();
+}
+
+void WebFrameWidgetImpl::RecordStartOfFrameMetrics() {
+  if (!LocalRootImpl())
+    return;
+
+  LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().BeginMainFrame();
+}
+
+void WebFrameWidgetImpl::RecordEndOfFrameMetrics(
+    base::TimeTicks frame_begin_time,
+    cc::ActiveFrameSequenceTrackers trackers) {
+  if (!LocalRootImpl())
+    return;
+
+  LocalRootImpl()
+      ->GetFrame()
+      ->View()
+      ->EnsureUkmAggregator()
+      .RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now(),
+                               trackers);
+}
+
+bool WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event) {
+  possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kTouch;
+  possible_drag_event_info_.location =
+      gfx::ToFlooredPoint(event.PositionInScreen());
+
+  bool move_cursor = false;
+  switch (event.GetType()) {
+    case WebInputEvent::Type::kGestureScrollBegin: {
+      if (event.data.scroll_begin.cursor_control) {
+        swipe_to_move_cursor_activated_ = true;
+        move_cursor = true;
+      }
+      break;
+    }
+    case WebInputEvent::Type::kGestureScrollUpdate: {
+      if (swipe_to_move_cursor_activated_)
+        move_cursor = true;
+      break;
+    }
+    case WebInputEvent::Type::kGestureScrollEnd: {
+      if (swipe_to_move_cursor_activated_) {
+        swipe_to_move_cursor_activated_ = false;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  // TODO(crbug.com/1140106): Place cursor for scroll begin other than just move
+  // cursor.
+  if (move_cursor) {
+    WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+    if (focused_frame) {
+      gfx::Point base(event.PositionInWidget().x(),
+                      event.PositionInWidget().y());
+      focused_frame->MoveCaretSelection(base);
+    }
+    return true;
+  }
+  return false;
+}
+
+void WebFrameWidgetImpl::WillHandleMouseEvent(const WebMouseEvent& event) {
+  possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kMouse;
+  possible_drag_event_info_.location =
+      gfx::Point(event.PositionInScreen().x(), event.PositionInScreen().y());
+}
+
+void WebFrameWidgetImpl::ObserveGestureEventAndResult(
+    const WebGestureEvent& gesture_event,
+    const gfx::Vector2dF& unused_delta,
+    const cc::OverscrollBehavior& overscroll_behavior,
+    bool event_processed) {
+  if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
+    return;
+
+  cc::InputHandlerScrollResult scroll_result;
+  scroll_result.did_scroll = event_processed;
+  scroll_result.did_overscroll_root = !unused_delta.IsZero();
+  scroll_result.unused_scroll_delta = unused_delta;
+  scroll_result.overscroll_behavior = overscroll_behavior;
+
+  widget_base_->widget_input_handler_manager()->ObserveGestureEventOnMainThread(
+      gesture_event, scroll_result);
+}
+
+void WebFrameWidgetImpl::DidHandleKeyEvent() {
+  ClearEditCommands();
+}
+
+WebTextInputType WebFrameWidgetImpl::GetTextInputType() {
+  if (ShouldDispatchImeEventsToPlugin()) {
+    return GetFocusedPluginContainer()->GetPluginTextInputType();
+  }
+
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return WebTextInputType::kWebTextInputTypeNone;
+  return controller->TextInputType();
+}
+
+void WebFrameWidgetImpl::SetCursorVisibilityState(bool is_visible) {
+  GetPage()->SetIsCursorVisible(is_visible);
+}
+
+void WebFrameWidgetImpl::ApplyViewportChangesForTesting(
+    const ApplyViewportChangesArgs& args) {
+  widget_base_->ApplyViewportChanges(args);
+}
+
+void WebFrameWidgetImpl::SetDisplayMode(mojom::blink::DisplayMode mode) {
+  if (mode != display_mode_) {
+    display_mode_ = mode;
+    LocalFrame* frame = LocalRootImpl()->GetFrame();
+    frame->MediaQueryAffectingValueChangedForLocalSubtree(
+        MediaValueChange::kOther);
+  }
+}
+
+void WebFrameWidgetImpl::SetWindowSegments(
+    const std::vector<gfx::Rect>& window_segments_param) {
+  WebVector<gfx::Rect> window_segments(window_segments_param);
+  if (!window_segments_.Equals(window_segments)) {
+    window_segments_ = window_segments;
+    LocalFrame* frame = LocalRootImpl()->GetFrame();
+    frame->WindowSegmentsChanged(window_segments_);
+
+    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+        [](const std::vector<gfx::Rect>& window_segments,
+           RemoteFrame* remote_frame) {
+          remote_frame->Client()->DidChangeRootWindowSegments(window_segments);
+        },
+        window_segments_param));
+  }
+}
+
+void WebFrameWidgetImpl::SetCursor(const ui::Cursor& cursor) {
+  widget_base_->SetCursor(cursor);
+}
+
+bool WebFrameWidgetImpl::HandlingInputEvent() {
+  return widget_base_->input_handler().handling_input_event();
+}
+
+void WebFrameWidgetImpl::SetHandlingInputEvent(bool handling) {
+  widget_base_->input_handler().set_handling_input_event(handling);
+}
+
+void WebFrameWidgetImpl::ProcessInputEventSynchronouslyForTesting(
+    const WebCoalescedInputEvent& event,
+    HandledEventCallback callback) {
+  widget_base_->input_handler().HandleInputEvent(event, nullptr,
+                                                 std::move(callback));
+}
+
+WebInputEventResult WebFrameWidgetImpl::DispatchBufferedTouchEvents() {
+  CHECK(LocalRootImpl());
+
+  if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
+    devtools->DispatchBufferedTouchEvents();
+
+  return LocalRootImpl()
+      ->GetFrame()
+      ->GetEventHandler()
+      .DispatchBufferedTouchEvents();
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
+    const WebCoalescedInputEvent& coalesced_event) {
+  const WebInputEvent& input_event = coalesced_event.Event();
+  TRACE_EVENT1("input,rail", "WebFrameWidgetImpl::HandleInputEvent", "type",
+               WebInputEvent::GetName(input_event.GetType()));
+  DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
+  CHECK(LocalRootImpl());
+
+  // Only record metrics for the main frame.
+  if (ForMainFrame()) {
+    GetPage()->GetVisualViewport().StartTrackingPinchStats();
+  }
+
+  // If a drag-and-drop operation is in progress, ignore input events except
+  // PointerCancel.
+  if (doing_drag_and_drop_ &&
+      input_event.GetType() != WebInputEvent::Type::kPointerCancel)
+    return WebInputEventResult::kHandledSuppressed;
+
+  // Don't handle events once we've started shutting down.
+  if (!GetPage())
+    return WebInputEventResult::kNotHandled;
+
+  if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) {
+    auto result = devtools->HandleInputEvent(input_event);
+    if (result != WebInputEventResult::kNotHandled)
+      return result;
+  }
+
+  // Report the event to be NOT processed by WebKit, so that the browser can
+  // handle it appropriately.
+  if (IgnoreInputEvents())
+    return WebInputEventResult::kNotHandled;
+
+  base::AutoReset<const WebInputEvent*> current_event_change(
+      &CurrentInputEvent::current_input_event_, &input_event);
+  UIEventWithKeyState::ClearNewTabModifierSetFromIsolatedWorld();
+
+  if (GetPage()->GetPointerLockController().IsPointerLocked() &&
+      WebInputEvent::IsMouseEventType(input_event.GetType())) {
+    PointerLockMouseEvent(coalesced_event);
+    return WebInputEventResult::kHandledSystem;
+  }
+
+  /// These metrics are only captured for the main frame.
+  if (ForMainFrame()) {
+    Document& main_frame_document = *LocalRootImpl()->GetFrame()->GetDocument();
+
+    if (input_event.GetType() != WebInputEvent::Type::kMouseMove) {
+      FirstMeaningfulPaintDetector::From(main_frame_document)
+          .NotifyInputEvent();
+    }
+
+    if (input_event.GetType() != WebInputEvent::Type::kMouseMove &&
+        input_event.GetType() != WebInputEvent::Type::kMouseEnter &&
+        input_event.GetType() != WebInputEvent::Type::kMouseLeave) {
+      InteractiveDetector* interactive_detector(
+          InteractiveDetector::From(main_frame_document));
+      if (interactive_detector) {
+        interactive_detector->OnInvalidatingInputEvent(input_event.TimeStamp());
+      }
+    }
+  }
+
+  NotifyInputObservers(coalesced_event);
+
+  // Notify the focus frame of the input. Note that the other frames are not
+  // notified as input is only handled by the focused frame.
+  Frame* frame = FocusedCoreFrame();
+  if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
+    if (auto* content_capture_manager =
+            local_frame->LocalFrameRoot().GetContentCaptureManager()) {
+      content_capture_manager->NotifyInputEvent(input_event.GetType(),
+                                                *local_frame);
+    }
+  }
+
+  // Skip the pointerrawupdate for mouse capture case.
+  if (mouse_capture_element_ &&
+      input_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)
+    return WebInputEventResult::kHandledSystem;
+
+  if (mouse_capture_element_ &&
+      WebInputEvent::IsMouseEventType(input_event.GetType()))
+    return HandleCapturedMouseEvent(coalesced_event);
+
+  // FIXME: This should take in the intended frame, not the local frame
+  // root.
+  return PageWidgetDelegate::HandleInputEvent(*this, coalesced_event,
+                                              LocalRootImpl()->GetFrame());
+}
+
+WebInputEventResult WebFrameWidgetImpl::HandleCapturedMouseEvent(
+    const WebCoalescedInputEvent& coalesced_event) {
+  const WebInputEvent& input_event = coalesced_event.Event();
+  TRACE_EVENT1("input", "captured mouse event", "type", input_event.GetType());
+  // Save |mouse_capture_element_| since |MouseCaptureLost()| will clear it.
+  HTMLPlugInElement* element = mouse_capture_element_;
+
+  // Not all platforms call mouseCaptureLost() directly.
+  if (input_event.GetType() == WebInputEvent::Type::kMouseUp) {
+    SetMouseCapture(false);
+    MouseCaptureLost();
+  }
+
+  AtomicString event_type;
+  switch (input_event.GetType()) {
+    case WebInputEvent::Type::kMouseEnter:
+      event_type = event_type_names::kMouseover;
+      break;
+    case WebInputEvent::Type::kMouseMove:
+      event_type = event_type_names::kMousemove;
+      break;
+    case WebInputEvent::Type::kPointerRawUpdate:
+      // There will be no mouse event for rawupdate events.
+      event_type = event_type_names::kPointerrawupdate;
+      break;
+    case WebInputEvent::Type::kMouseLeave:
+      event_type = event_type_names::kMouseout;
+      break;
+    case WebInputEvent::Type::kMouseDown:
+      event_type = event_type_names::kMousedown;
+      LocalFrame::NotifyUserActivation(
+          element->GetDocument().GetFrame(),
+          mojom::blink::UserActivationNotificationType::kInteraction);
+      break;
+    case WebInputEvent::Type::kMouseUp:
+      event_type = event_type_names::kMouseup;
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  WebMouseEvent transformed_event =
+      TransformWebMouseEvent(LocalRootImpl()->GetFrameView(),
+                             static_cast<const WebMouseEvent&>(input_event));
+  if (LocalFrame* frame = element->GetDocument().GetFrame()) {
+    frame->GetEventHandler().HandleTargetedMouseEvent(
+        element, transformed_event, event_type,
+        TransformWebMouseEventVector(
+            LocalRootImpl()->GetFrameView(),
+            coalesced_event.GetCoalescedEventsPointers()),
+        TransformWebMouseEventVector(
+            LocalRootImpl()->GetFrameView(),
+            coalesced_event.GetPredictedEventsPointers()));
+  }
+  return WebInputEventResult::kHandledSystem;
+}
+
+void WebFrameWidgetImpl::UpdateTextInputState() {
+  widget_base_->UpdateTextInputState();
+}
+
+void WebFrameWidgetImpl::UpdateSelectionBounds() {
+  widget_base_->UpdateSelectionBounds();
+}
+
+void WebFrameWidgetImpl::ShowVirtualKeyboard() {
+  widget_base_->ShowVirtualKeyboard();
+}
+
+void WebFrameWidgetImpl::FlushInputProcessedCallback() {
+  widget_base_->FlushInputProcessedCallback();
+}
+
+void WebFrameWidgetImpl::CancelCompositionForPepper() {
+  widget_base_->CancelCompositionForPepper();
+}
+
+void WebFrameWidgetImpl::RequestMouseLock(
+    bool has_transient_user_activation,
+    bool request_unadjusted_movement,
+    mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback) {
+  mojom::blink::WidgetInputHandlerHost* host =
+      widget_base_->widget_input_handler_manager()->GetWidgetInputHandlerHost();
+
+  // If we don't have a host just leave the callback uncalled. This simulates
+  // the browser indefinitely postponing the mouse request which is valid.
+  // Note that |callback| is not a mojo bound callback (until it is passed
+  // into the mojo interface) and can be destructed without invoking the
+  // callback. It does share the same signature as the mojo definition
+  // for simplicity.
+  if (host) {
+    host->RequestMouseLock(has_transient_user_activation,
+                           request_unadjusted_movement, std::move(callback));
+  }
+}
+
+void WebFrameWidgetImpl::MouseCaptureLost() {
+  TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
+                                  TRACE_ID_LOCAL(this));
+  mouse_capture_element_ = nullptr;
+}
+
+void WebFrameWidgetImpl::ApplyVisualProperties(
+    const VisualProperties& visual_properties) {
+  widget_base_->UpdateVisualProperties(visual_properties);
+}
+
+bool WebFrameWidgetImpl::IsFullscreenGranted() {
+  return is_fullscreen_granted_;
+}
+
+bool WebFrameWidgetImpl::PinchGestureActiveInMainFrame() {
+  return is_pinch_gesture_active_in_mainframe_;
+}
+
+float WebFrameWidgetImpl::PageScaleInMainFrame() {
+  return page_scale_factor_in_mainframe_;
+}
+
+void WebFrameWidgetImpl::UpdateSurfaceAndScreenInfo(
+    const viz::LocalSurfaceId& new_local_surface_id,
+    const gfx::Rect& compositor_viewport_pixel_rect,
+    const ScreenInfo& new_screen_info) {
+  widget_base_->UpdateSurfaceAndScreenInfo(
+      new_local_surface_id, compositor_viewport_pixel_rect, new_screen_info);
+}
+
+void WebFrameWidgetImpl::UpdateScreenInfo(const ScreenInfo& new_screen_info) {
+  widget_base_->UpdateScreenInfo(new_screen_info);
+}
+
+void WebFrameWidgetImpl::UpdateSurfaceAndCompositorRect(
+    const viz::LocalSurfaceId& new_local_surface_id,
+    const gfx::Rect& compositor_viewport_pixel_rect) {
+  widget_base_->UpdateSurfaceAndCompositorRect(new_local_surface_id,
+                                               compositor_viewport_pixel_rect);
+}
+
+void WebFrameWidgetImpl::UpdateCompositorViewportRect(
+    const gfx::Rect& compositor_viewport_pixel_rect) {
+  widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
+}
+
+const ScreenInfo& WebFrameWidgetImpl::GetScreenInfo() {
+  return widget_base_->GetScreenInfo();
+}
+
+gfx::Rect WebFrameWidgetImpl::WindowRect() {
+  return widget_base_->WindowRect();
+}
+
+gfx::Rect WebFrameWidgetImpl::ViewRect() {
+  return widget_base_->ViewRect();
+}
+
+void WebFrameWidgetImpl::SetScreenRects(const gfx::Rect& widget_screen_rect,
+                                        const gfx::Rect& window_screen_rect) {
+  widget_base_->SetScreenRects(widget_screen_rect, window_screen_rect);
+}
+
+gfx::Size WebFrameWidgetImpl::VisibleViewportSizeInDIPs() {
+  return widget_base_->VisibleViewportSizeInDIPs();
+}
+
+void WebFrameWidgetImpl::SetPendingWindowRect(
+    const gfx::Rect& window_screen_rect) {
+  widget_base_->SetPendingWindowRect(window_screen_rect);
+}
+
+void WebFrameWidgetImpl::AckPendingWindowRect() {
+  widget_base_->AckPendingWindowRect();
+}
+
+bool WebFrameWidgetImpl::IsHidden() const {
+  return widget_base_->is_hidden();
+}
+
+WebString WebFrameWidgetImpl::GetLastToolTipTextForTesting() const {
+  return GetPage()->GetChromeClient().GetLastToolTipTextForTesting();
+}
+
+float WebFrameWidgetImpl::GetEmulatorScale() {
+  if (device_emulator_)
+    return device_emulator_->scale();
+  return 1.0f;
+}
+
+void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
+    mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
+  DCHECK(ForSubframe());
+  GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
+      std::move(sizing_info));
+}
+
+void WebFrameWidgetImpl::AutoscrollStart(const gfx::PointF& position) {
+  GetAssociatedFrameWidgetHost()->AutoscrollStart(std::move(position));
+}
+
+void WebFrameWidgetImpl::AutoscrollFling(const gfx::Vector2dF& velocity) {
+  GetAssociatedFrameWidgetHost()->AutoscrollFling(std::move(velocity));
+}
+
+void WebFrameWidgetImpl::AutoscrollEnd() {
+  GetAssociatedFrameWidgetHost()->AutoscrollEnd();
+}
+
+void WebFrameWidgetImpl::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
+  if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
+    NotifySwapAndPresentationTime(
+        base::NullCallback(),
+        WTF::Bind(&WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout,
+                  WrapPersistent(this)));
+  }
+
+  ForEachLocalFrameControlledByWidget(
+      local_root_->GetFrame(),
+      WTF::BindRepeating(
+          [](WebMeaningfulLayout layout_type, WebLocalFrame* local_frame) {
+            local_frame->Client()->DidMeaningfulLayout(layout_type);
+          },
+          layout_type));
+}
+
+void WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout(
+    blink::WebSwapResult,
+    base::TimeTicks) {
+  GetAssociatedFrameWidgetHost()->DidFirstVisuallyNonEmptyPaint();
+}
+
+void WebFrameWidgetImpl::RequestAnimationAfterDelay(
+    const base::TimeDelta& delay) {
+  DCHECK(request_animation_after_delay_timer_.get());
+  if (request_animation_after_delay_timer_->IsActive() &&
+      request_animation_after_delay_timer_->NextFireInterval() > delay) {
+    request_animation_after_delay_timer_->Stop();
+  }
+  if (!request_animation_after_delay_timer_->IsActive()) {
+    request_animation_after_delay_timer_->StartOneShot(delay, FROM_HERE);
+  }
+}
+
+void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
+  if (!View()->does_composite()) {
+    DCHECK(ForMainFrame());
+    DCHECK(!layer);
+    return;
+  }
+
+  // Set up some initial state before we are setting the layer.
+  if (ForSubframe() && layer) {
+    // Child local roots will always have a transparent background color.
+    widget_base_->LayerTreeHost()->set_background_color(SK_ColorTRANSPARENT);
+    // Pass the limits even though this is for subframes, as the limits will
+    // be needed in setting the raster scale.
+    SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
+                               View()->MinimumPageScaleFactor(),
+                               View()->MaximumPageScaleFactor());
+  }
+
+  bool root_layer_exists = !!layer;
+  widget_base_->LayerTreeHost()->SetRootLayer(std::move(layer));
+
+  // Notify the WebView that we did set a layer.
+  if (ForMainFrame()) {
+    View()->DidChangeRootLayer(root_layer_exists);
+  }
+}
+
+void WebFrameWidgetImpl::RequestAnimationAfterDelayTimerFired(TimerBase*) {
+  if (client_)
+    client_->ScheduleAnimation();
+}
+
+base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
+WebFrameWidgetImpl::EnsureCompositorMutatorDispatcher(
+    scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner) {
+  if (!mutator_task_runner_) {
+    widget_base_->LayerTreeHost()->SetLayerTreeMutator(
+        AnimationWorkletMutatorDispatcherImpl::CreateCompositorThreadClient(
+            &mutator_dispatcher_, &mutator_task_runner_));
+  }
+
+  DCHECK(mutator_task_runner_);
+  *mutator_task_runner = mutator_task_runner_;
+  return mutator_dispatcher_;
+}
+
+HitTestResult WebFrameWidgetImpl::CoreHitTestResultAt(
+    const gfx::PointF& point_in_viewport) {
+  LocalFrameView* view = LocalRootImpl()->GetFrameView();
+  FloatPoint point_in_root_frame(
+      view->ViewportToFrame(FloatPoint(point_in_viewport)));
+  return HitTestResultForRootFramePos(point_in_root_frame);
+}
+
+cc::AnimationHost* WebFrameWidgetImpl::AnimationHost() const {
+  return widget_base_->AnimationHost();
+}
+
+base::WeakPtr<PaintWorkletPaintDispatcher>
+WebFrameWidgetImpl::EnsureCompositorPaintDispatcher(
+    scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner) {
+  // We check paint_task_runner_ not paint_dispatcher_ because the dispatcher is
+  // a base::WeakPtr that should only be used on the compositor thread.
+  if (!paint_task_runner_) {
+    widget_base_->LayerTreeHost()->SetPaintWorkletLayerPainter(
+        PaintWorkletPaintDispatcher::CreateCompositorThreadPainter(
+            &paint_dispatcher_));
+    paint_task_runner_ = Thread::CompositorThread()->GetTaskRunner();
+  }
+  DCHECK(paint_task_runner_);
+  *paint_task_runner = paint_task_runner_;
+  return paint_dispatcher_;
+}
+
+void WebFrameWidgetImpl::SetDelegatedInkMetadata(
+    std::unique_ptr<viz::DelegatedInkMetadata> metadata) {
+  widget_base_->LayerTreeHost()->SetDelegatedInkMetadata(std::move(metadata));
+}
+
+// Enables measuring and reporting both presentation times and swap times in
+// swap promises.
+class ReportTimeSwapPromise : public cc::SwapPromise {
+ public:
+  ReportTimeSwapPromise(WebReportTimeCallback swap_time_callback,
+                        WebReportTimeCallback presentation_time_callback,
+                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                        WebFrameWidgetImpl* widget)
+      : swap_time_callback_(std::move(swap_time_callback)),
+        presentation_time_callback_(std::move(presentation_time_callback)),
+        task_runner_(std::move(task_runner)),
+        widget_(widget) {}
+  ~ReportTimeSwapPromise() override = default;
+
+  void DidActivate() override {}
+
+  void WillSwap(viz::CompositorFrameMetadata* metadata) override {
+    DCHECK_GT(metadata->frame_token, 0u);
+    // The interval between the current swap and its presentation time is
+    // reported in UMA (see corresponding code in DidSwap() below).
+    frame_token_ = metadata->frame_token;
+  }
+
+  void DidSwap() override {
+    DCHECK_GT(frame_token_, 0u);
+    PostCrossThreadTask(
+        *task_runner_, FROM_HERE,
+        CrossThreadBindOnce(
+            &RunCallbackAfterSwap, widget_, base::TimeTicks::Now(),
+            std::move(swap_time_callback_),
+            std::move(presentation_time_callback_), frame_token_));
+  }
+
+  cc::SwapPromise::DidNotSwapAction DidNotSwap(
+      DidNotSwapReason reason) override {
+    WebSwapResult result;
+    switch (reason) {
+      case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
+        result = WebSwapResult::kDidNotSwapSwapFails;
+        break;
+      case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
+        result = WebSwapResult::kDidNotSwapCommitFails;
+        break;
+      case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
+        result = WebSwapResult::kDidNotSwapCommitNoUpdate;
+        break;
+      case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
+        result = WebSwapResult::kDidNotSwapActivationFails;
+        break;
+    }
+    // During a failed swap, return the current time regardless of whether we're
+    // using presentation or swap timestamps.
+    PostCrossThreadTask(
+        *task_runner_, FROM_HERE,
+        CrossThreadBindOnce(
+            [](WebSwapResult result, base::TimeTicks swap_time,
+               WebReportTimeCallback swap_time_callback,
+               WebReportTimeCallback presentation_time_callback) {
+              ReportTime(std::move(swap_time_callback), result, swap_time);
+              ReportTime(std::move(presentation_time_callback), result,
+                         swap_time);
+            },
+            result, base::TimeTicks::Now(), std::move(swap_time_callback_),
+            std::move(presentation_time_callback_)));
+    return DidNotSwapAction::BREAK_PROMISE;
+  }
+
+  int64_t TraceId() const override { return 0; }
+
+ private:
+  static void RunCallbackAfterSwap(
+      WebFrameWidgetImpl* widget,
+      base::TimeTicks swap_time,
+      WebReportTimeCallback swap_time_callback,
+      WebReportTimeCallback presentation_time_callback,
+      int frame_token) {
+    // If the widget was collected or the widget wasn't collected yet, but
+    // it was closed don't schedule a presentation callback.
+    if (widget && widget->widget_base_) {
+      widget->widget_base_->AddPresentationCallback(
+          frame_token,
+          WTF::Bind(&RunCallbackAfterPresentation,
+                    std::move(presentation_time_callback), swap_time));
+      ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
+                 swap_time);
+    } else {
+      ReportTime(std::move(swap_time_callback), WebSwapResult::kDidSwap,
+                 swap_time);
+      ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
+                 swap_time);
+    }
+  }
+
+  static void RunCallbackAfterPresentation(
+      WebReportTimeCallback presentation_time_callback,
+      base::TimeTicks swap_time,
+      base::TimeTicks presentation_time) {
+    DCHECK(!swap_time.is_null());
+    bool presentation_time_is_valid =
+        !presentation_time.is_null() && (presentation_time > swap_time);
+    UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
+                          presentation_time_is_valid);
+    if (presentation_time_is_valid) {
+      // This measures from 1ms to 10seconds.
+      UMA_HISTOGRAM_TIMES(
+          "PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime",
+          presentation_time - swap_time);
+    }
+    ReportTime(std::move(presentation_time_callback), WebSwapResult::kDidSwap,
+               presentation_time_is_valid ? presentation_time : swap_time);
+  }
+
+  static void ReportTime(WebReportTimeCallback callback,
+                         WebSwapResult result,
+                         base::TimeTicks time) {
+    if (callback)
+      std::move(callback).Run(result, time);
+  }
+
+  WebReportTimeCallback swap_time_callback_;
+  WebReportTimeCallback presentation_time_callback_;
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  CrossThreadWeakPersistent<WebFrameWidgetImpl> widget_;
+  uint32_t frame_token_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise);
+};
+
+void WebFrameWidgetImpl::NotifySwapAndPresentationTimeInBlink(
+    WebReportTimeCallback swap_time_callback,
+    WebReportTimeCallback presentation_time_callback) {
+  NotifySwapAndPresentationTime(std::move(swap_time_callback),
+                                std::move(presentation_time_callback));
+}
+
+void WebFrameWidgetImpl::NotifySwapAndPresentationTime(
+    WebReportTimeCallback swap_time_callback,
+    WebReportTimeCallback presentation_time_callback) {
+  if (!View()->does_composite())
+    return;
+  widget_base_->LayerTreeHost()->QueueSwapPromise(
+      std::make_unique<ReportTimeSwapPromise>(
+          std::move(swap_time_callback), std::move(presentation_time_callback),
+          widget_base_->LayerTreeHost()
+              ->GetTaskRunnerProvider()
+              ->MainThreadTaskRunner(),
+          this));
+}
+
+scheduler::WebRenderWidgetSchedulingState*
+WebFrameWidgetImpl::RendererWidgetSchedulingState() {
+  return widget_base_->RendererWidgetSchedulingState();
+}
+
+void WebFrameWidgetImpl::WaitForDebuggerWhenShown() {
+  local_root_->WaitForDebuggerWhenShown();
+}
+
+void WebFrameWidgetImpl::SetTextZoomFactor(float text_zoom_factor) {
+  local_root_->GetFrame()->SetTextZoomFactor(text_zoom_factor);
+}
+
+float WebFrameWidgetImpl::TextZoomFactor() {
+  return local_root_->GetFrame()->TextZoomFactor();
+}
+
+void WebFrameWidgetImpl::SetMainFrameOverlayColor(SkColor color) {
+  DCHECK(!local_root_->Parent());
+  local_root_->GetFrame()->SetMainFrameColorOverlay(color);
+}
+
+void WebFrameWidgetImpl::AddEditCommandForNextKeyEvent(const WebString& name,
+                                                       const WebString& value) {
+  edit_commands_.push_back(mojom::blink::EditCommand::New(name, value));
+}
+
+bool WebFrameWidgetImpl::HandleCurrentKeyboardEvent() {
+  bool did_execute_command = false;
+  WebLocalFrame* frame = FocusedWebLocalFrameInWidget();
+  if (!frame)
+    frame = local_root_;
+  for (const auto& command : edit_commands_) {
+    // In gtk and cocoa, it's possible to bind multiple edit commands to one
+    // key (but it's the exception). Once one edit command is not executed, it
+    // seems safest to not execute the rest.
+    if (!frame->ExecuteCommand(command->name, command->value))
+      break;
+    did_execute_command = true;
+  }
+
+  return did_execute_command;
+}
+
+void WebFrameWidgetImpl::ClearEditCommands() {
+  edit_commands_ = Vector<mojom::blink::EditCommandPtr>();
+}
+
+WebTextInputInfo WebFrameWidgetImpl::TextInputInfo() {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return WebTextInputInfo();
+  return controller->TextInputInfo();
+}
+
+ui::mojom::blink::VirtualKeyboardVisibilityRequest
+WebFrameWidgetImpl::GetLastVirtualKeyboardVisibilityRequest() {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE;
+  return controller->GetLastVirtualKeyboardVisibilityRequest();
+}
+
+bool WebFrameWidgetImpl::ShouldSuppressKeyboardForFocusedElement() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return false;
+  return focused_frame->ShouldSuppressKeyboardForFocusedElement();
+}
+
+void WebFrameWidgetImpl::GetEditContextBoundsInWindow(
+    base::Optional<gfx::Rect>* edit_context_control_bounds,
+    base::Optional<gfx::Rect>* edit_context_selection_bounds) {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return;
+  WebRect control_bounds;
+  WebRect selection_bounds;
+  controller->GetLayoutBounds(&control_bounds, &selection_bounds);
+  *edit_context_control_bounds =
+      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(control_bounds));
+  if (controller->IsEditContextActive()) {
+    *edit_context_selection_bounds =
+        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(selection_bounds));
+  }
+}
+
+int32_t WebFrameWidgetImpl::ComputeWebTextInputNextPreviousFlags() {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return 0;
+  return controller->ComputeWebTextInputNextPreviousFlags();
+}
+
+void WebFrameWidgetImpl::ResetVirtualKeyboardVisibilityRequest() {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return;
+  controller->SetVirtualKeyboardVisibilityRequest(
+      ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE);
+  ;
+}
+
+bool WebFrameWidgetImpl::GetSelectionBoundsInWindow(
+    gfx::Rect* focus,
+    gfx::Rect* anchor,
+    base::i18n::TextDirection* focus_dir,
+    base::i18n::TextDirection* anchor_dir,
+    bool* is_anchor_first) {
+  if (ShouldDispatchImeEventsToPlugin()) {
+    // TODO(kinaba) http://crbug.com/101101
+    // Current Pepper IME API does not handle selection bounds. So we simply
+    // use the caret position as an empty range for now. It will be updated
+    // after Pepper API equips features related to surrounding text retrieval.
+    gfx::Rect pepper_caret_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
+        GetFocusedPluginContainer()->GetPluginCaretBounds());
+    if (pepper_caret_in_dips == *focus && pepper_caret_in_dips == *anchor)
+      return false;
+    *focus = pepper_caret_in_dips;
+    *anchor = *focus;
+    return true;
+  }
+  gfx::Rect focus_root_frame;
+  gfx::Rect anchor_root_frame;
+  CalculateSelectionBounds(focus_root_frame, anchor_root_frame);
+  gfx::Rect focus_rect_in_dips =
+      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(focus_root_frame));
+  gfx::Rect anchor_rect_in_dips =
+      widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(anchor_root_frame));
+
+  // if the bounds are the same return false.
+  if (focus_rect_in_dips == *focus && anchor_rect_in_dips == *anchor)
+    return false;
+  *focus = focus_rect_in_dips;
+  *anchor = anchor_rect_in_dips;
+
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return true;
+  focused_frame->SelectionTextDirection(*focus_dir, *anchor_dir);
+  *is_anchor_first = focused_frame->IsSelectionAnchorFirst();
+  return true;
+}
+
+void WebFrameWidgetImpl::ClearTextInputState() {
+  widget_base_->ClearTextInputState();
+}
+
+bool WebFrameWidgetImpl::IsPasting() {
+  return widget_base_->is_pasting();
+}
+
+bool WebFrameWidgetImpl::HandlingSelectRange() {
+  return widget_base_->handling_select_range();
+}
+
+void WebFrameWidgetImpl::SetFocus(bool focus) {
+  widget_base_->SetFocus(focus);
+}
+
+bool WebFrameWidgetImpl::HasFocus() {
+  return widget_base_->has_focus();
+}
+
+void WebFrameWidgetImpl::SetToolTipText(const String& tooltip_text,
+                                        TextDirection dir) {
+  widget_base_->SetToolTipText(tooltip_text, dir);
+}
+
+void WebFrameWidgetImpl::DidOverscroll(
+    const gfx::Vector2dF& overscroll_delta,
+    const gfx::Vector2dF& accumulated_overscroll,
+    const gfx::PointF& position,
+    const gfx::Vector2dF& velocity) {
+#if defined(OS_MAC)
+  // On OSX the user can disable the elastic overscroll effect. If that's the
+  // case, don't forward the overscroll notification.
+  if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
+    return;
+#endif
+
+  cc::OverscrollBehavior overscroll_behavior =
+      widget_base_->LayerTreeHost()->overscroll_behavior();
+  if (!widget_base_->input_handler().DidOverscrollFromBlink(
+          overscroll_delta, accumulated_overscroll, position, velocity,
+          overscroll_behavior))
+    return;
+
+  // If we're currently handling an event, stash the overscroll data such that
+  // it can be bundled in the event ack.
+  if (mojom::blink::WidgetInputHandlerHost* host =
+          widget_base_->widget_input_handler_manager()
+              ->GetWidgetInputHandlerHost()) {
+    host->DidOverscroll(mojom::blink::DidOverscrollParams::New(
+        accumulated_overscroll, overscroll_delta, velocity, position,
+        overscroll_behavior));
+  }
+}
+
+void WebFrameWidgetImpl::InjectGestureScrollEvent(
+    blink::WebGestureDevice device,
+    const gfx::Vector2dF& delta,
+    ui::ScrollGranularity granularity,
+    cc::ElementId scrollable_area_element_id,
+    blink::WebInputEvent::Type injected_type) {
+  if (RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
+    // create a GestureScroll Event and post it to the compositor thread
+    // TODO(crbug.com/1126098) use original input event's timestamp.
+    // TODO(crbug.com/1082590) ensure continuity in scroll metrics collection
+    base::TimeTicks now = base::TimeTicks::Now();
+    std::unique_ptr<WebGestureEvent> gesture_event =
+        WebGestureEvent::GenerateInjectedScrollGesture(
+            injected_type, now, device, gfx::PointF(0, 0), delta, granularity);
+    if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
+      gesture_event->data.scroll_begin.scrollable_area_element_id =
+          scrollable_area_element_id.GetStableId();
+      gesture_event->data.scroll_begin.main_thread_hit_tested = true;
+    }
+
+    widget_base_->widget_input_handler_manager()
+        ->DispatchScrollGestureToCompositor(std::move(gesture_event));
+  } else {
+    widget_base_->input_handler().InjectGestureScrollEvent(
+        device, delta, granularity, scrollable_area_element_id, injected_type);
+  }
+}
+
+void WebFrameWidgetImpl::DidChangeCursor(const ui::Cursor& cursor) {
+  widget_base_->SetCursor(cursor);
+  Client()->DidChangeCursor(cursor);
+}
+
+bool WebFrameWidgetImpl::SetComposition(
+    const String& text,
+    const Vector<ui::ImeTextSpan>& ime_text_spans,
+    const gfx::Range& replacement_range,
+    int selection_start,
+    int selection_end) {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return false;
+
+  return controller->SetComposition(
+      text, ime_text_spans,
+      replacement_range.IsValid()
+          ? WebRange(replacement_range.start(), replacement_range.length())
+          : WebRange(),
+      selection_start, selection_end);
+}
+
+void WebFrameWidgetImpl::CommitText(
+    const String& text,
+    const Vector<ui::ImeTextSpan>& ime_text_spans,
+    const gfx::Range& replacement_range,
+    int relative_cursor_pos) {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return;
+  controller->CommitText(
+      text, ime_text_spans,
+      replacement_range.IsValid()
+          ? WebRange(replacement_range.start(), replacement_range.length())
+          : WebRange(),
+      relative_cursor_pos);
+}
+
+void WebFrameWidgetImpl::FinishComposingText(bool keep_selection) {
+  WebInputMethodController* controller = GetActiveWebInputMethodController();
+  if (!controller)
+    return;
+  controller->FinishComposingText(
+      keep_selection ? WebInputMethodController::kKeepSelection
+                     : WebInputMethodController::kDoNotKeepSelection);
+}
+
+bool WebFrameWidgetImpl::IsProvisional() {
+  return LocalRoot()->IsProvisional();
+}
+
+uint64_t WebFrameWidgetImpl::GetScrollableContainerIdAt(
+    const gfx::PointF& point_in_dips) {
+  gfx::PointF point = widget_base_->DIPsToBlinkSpace(point_in_dips);
+  return HitTestResultAt(point).GetScrollableContainerId();
+}
+
+bool WebFrameWidgetImpl::ShouldHandleImeEvents() {
+  if (ForMainFrame()) {
+    return HasFocus();
+  } else {
+    // TODO(ekaramad): main frame widget returns true only if it has focus.
+    // We track page focus in all WebViews on the page but the WebFrameWidgets
+    // corresponding to child local roots do not get the update. For now, this
+    // method returns true when the WebFrameWidget is for a child local frame,
+    // i.e., IME events will be processed regardless of page focus. We should
+    // revisit this after page focus for OOPIFs has been fully resolved
+    // (https://crbug.com/689777).
+    return LocalRootImpl();
+  }
+}
+
+void WebFrameWidgetImpl::SetEditCommandsForNextKeyEvent(
+    Vector<mojom::blink::EditCommandPtr> edit_commands) {
+  edit_commands_ = std::move(edit_commands);
+}
+
+void WebFrameWidgetImpl::FocusChangeComplete() {
+  blink::WebLocalFrame* focused = LocalRoot()->View()->FocusedFrame();
+
+  if (focused && focused->AutofillClient())
+    focused->AutofillClient()->DidCompleteFocusChangeInFrame();
+}
+
+void WebFrameWidgetImpl::ShowVirtualKeyboardOnElementFocus() {
+  widget_base_->ShowVirtualKeyboardOnElementFocus();
+}
+
+void WebFrameWidgetImpl::ProcessTouchAction(WebTouchAction touch_action) {
+  widget_base_->ProcessTouchAction(touch_action);
+}
+
+void WebFrameWidgetImpl::DidHandleGestureEvent(const WebGestureEvent& event) {
+#if defined(OS_ANDROID) || defined(USE_AURA)
+  if (event.GetType() == WebInputEvent::Type::kGestureTap) {
+    widget_base_->ShowVirtualKeyboard();
+  } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) {
+    WebInputMethodController* controller = GetActiveWebInputMethodController();
+    if (!controller || controller->TextInputInfo().value.IsEmpty())
+      widget_base_->UpdateTextInputState();
+    else
+      widget_base_->ShowVirtualKeyboard();
+  }
+#endif
+}
+
+void WebFrameWidgetImpl::SetHasPointerRawUpdateEventHandlers(
+    bool has_handlers) {
+  widget_base_->widget_input_handler_manager()
+      ->input_event_queue()
+      ->HasPointerRawUpdateEventHandlers(has_handlers);
+}
+
+void WebFrameWidgetImpl::SetNeedsLowLatencyInput(bool needs_low_latency) {
+  widget_base_->widget_input_handler_manager()
+      ->input_event_queue()
+      ->SetNeedsLowLatency(needs_low_latency);
+}
+
+void WebFrameWidgetImpl::RequestUnbufferedInputEvents() {
+  widget_base_->widget_input_handler_manager()
+      ->input_event_queue()
+      ->RequestUnbufferedInputEvents();
+}
+
+void WebFrameWidgetImpl::SetNeedsUnbufferedInputForDebugger(bool unbuffered) {
+  widget_base_->widget_input_handler_manager()
+      ->input_event_queue()
+      ->SetNeedsUnbufferedInputForDebugger(unbuffered);
+}
+
+void WebFrameWidgetImpl::DidNavigate() {
+  // The input handler wants to know about navigation so that it can
+  // suppress input until the newly navigated page has a committed frame.
+  // It also resets the state for UMA reporting of input arrival with respect
+  // to document lifecycle.
+  if (!widget_base_->widget_input_handler_manager())
+    return;
+  widget_base_->widget_input_handler_manager()->DidNavigate();
+}
+
+void WebFrameWidgetImpl::SetMouseCapture(bool capture) {
+  if (mojom::blink::WidgetInputHandlerHost* host =
+          widget_base_->widget_input_handler_manager()
+              ->GetWidgetInputHandlerHost()) {
+    host->SetMouseCapture(capture);
+  }
+}
+
+gfx::Range WebFrameWidgetImpl::CompositionRange() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame || ShouldDispatchImeEventsToPlugin())
+    return gfx::Range::InvalidRange();
+
+  blink::WebInputMethodController* controller =
+      focused_frame->GetInputMethodController();
+  WebRange web_range = controller->CompositionRange();
+  if (web_range.IsNull())
+    return gfx::Range::InvalidRange();
+  return gfx::Range(web_range.StartOffset(), web_range.EndOffset());
+}
+
+void WebFrameWidgetImpl::GetCompositionCharacterBoundsInWindow(
+    Vector<gfx::Rect>* bounds_in_dips) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame || ShouldDispatchImeEventsToPlugin())
+    return;
+  blink::WebInputMethodController* controller =
+      focused_frame->GetInputMethodController();
+  blink::WebVector<blink::WebRect> bounds_from_blink;
+  if (!controller->GetCompositionCharacterBounds(bounds_from_blink))
+    return;
+
+  for (auto& rect : bounds_from_blink) {
+    bounds_in_dips->push_back(
+        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(rect)));
+  }
+}
+
+void WebFrameWidgetImpl::AddImeTextSpansToExistingText(
+    uint32_t start,
+    uint32_t end,
+    const Vector<ui::ImeTextSpan>& ime_text_spans) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->AddImeTextSpansToExistingText(ime_text_spans, start, end);
+}
+
+Vector<ui::mojom::blink::ImeTextSpanInfoPtr>
+WebFrameWidgetImpl::GetImeTextSpansInfo(
+    const WebVector<ui::ImeTextSpan>& ime_text_spans) {
+  auto* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return Vector<ui::mojom::blink::ImeTextSpanInfoPtr>();
+
+  Vector<ui::mojom::blink::ImeTextSpanInfoPtr> ime_text_spans_info;
+
+  for (const auto& ime_text_span : ime_text_spans) {
+    WebRect webrect;
+    unsigned length = ime_text_span.end_offset - ime_text_span.start_offset;
+    focused_frame->FirstRectForCharacterRange(ime_text_span.start_offset,
+                                              length, webrect);
+
+    ime_text_spans_info.push_back(ui::mojom::blink::ImeTextSpanInfo::New(
+        ime_text_span,
+        widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(webrect))));
+  }
+  return ime_text_spans_info;
+}
+
+void WebFrameWidgetImpl::ClearImeTextSpansByType(uint32_t start,
+                                                 uint32_t end,
+                                                 ui::ImeTextSpan::Type type) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ClearImeTextSpansByType(type, start, end);
+}
+
+void WebFrameWidgetImpl::SetCompositionFromExistingText(
+    int32_t start,
+    int32_t end,
+    const Vector<ui::ImeTextSpan>& ime_text_spans) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->SetCompositionFromExistingText(start, end, ime_text_spans);
+}
+
+void WebFrameWidgetImpl::ExtendSelectionAndDelete(int32_t before,
+                                                  int32_t after) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExtendSelectionAndDelete(before, after);
+}
+
+void WebFrameWidgetImpl::DeleteSurroundingText(int32_t before, int32_t after) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->DeleteSurroundingText(before, after);
+}
+
+void WebFrameWidgetImpl::DeleteSurroundingTextInCodePoints(int32_t before,
+                                                           int32_t after) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->DeleteSurroundingTextInCodePoints(before, after);
+}
+
+void WebFrameWidgetImpl::SetEditableSelectionOffsets(int32_t start,
+                                                     int32_t end) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->SetEditableSelectionOffsets(start, end);
+}
+
+void WebFrameWidgetImpl::ExecuteEditCommand(const String& command,
+                                            const String& value) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(command, value);
+}
+
+void WebFrameWidgetImpl::Undo() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Undo"));
+}
+
+void WebFrameWidgetImpl::Redo() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Redo"));
+}
+
+void WebFrameWidgetImpl::Cut() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Cut"));
+}
+
+void WebFrameWidgetImpl::Copy() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Copy"));
+}
+
+void WebFrameWidgetImpl::CopyToFindPboard() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  To<WebLocalFrameImpl>(focused_frame)->CopyToFindPboard();
+}
+
+void WebFrameWidgetImpl::Paste() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Paste"));
+}
+
+void WebFrameWidgetImpl::PasteAndMatchStyle() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("PasteAndMatchStyle"));
+}
+
+void WebFrameWidgetImpl::Delete() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("Delete"));
+}
+
+void WebFrameWidgetImpl::SelectAll() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->ExecuteCommand(WebString::FromLatin1("SelectAll"));
+}
+
+void WebFrameWidgetImpl::CollapseSelection() {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  const blink::WebRange& range =
+      focused_frame->GetInputMethodController()->GetSelectionOffsets();
+  if (range.IsNull())
+    return;
+
+  focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0),
+                             blink::WebLocalFrame::kHideSelectionHandle,
+                             mojom::blink::SelectionMenuBehavior::kHide);
+}
+
+void WebFrameWidgetImpl::Replace(const String& word) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  if (!focused_frame->HasSelection())
+    focused_frame->SelectWordAroundCaret();
+  focused_frame->ReplaceSelection(word);
+  focused_frame->Client()->SyncSelectionIfRequired();
+}
+
+void WebFrameWidgetImpl::ReplaceMisspelling(const String& word) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  if (!focused_frame->HasSelection())
+    return;
+  focused_frame->ReplaceMisspelledRange(word);
+}
+
+void WebFrameWidgetImpl::SelectRange(const gfx::Point& base_in_dips,
+                                     const gfx::Point& extent_in_dips) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->SelectRange(
+      widget_base_->DIPsToRoundedBlinkSpace(base_in_dips),
+      widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
+}
+
+void WebFrameWidgetImpl::AdjustSelectionByCharacterOffset(
+    int32_t start,
+    int32_t end,
+    mojom::blink::SelectionMenuBehavior selection_menu_behavior) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  blink::WebRange range =
+      focused_frame->GetInputMethodController()->GetSelectionOffsets();
+  if (range.IsNull())
+    return;
+
+  // Sanity checks to disallow empty and out of range selections.
+  if (start - end > range.length() || range.StartOffset() + start < 0)
+    return;
+
+  // A negative adjust amount moves the selection towards the beginning of
+  // the document, a positive amount moves the selection towards the end of
+  // the document.
+  focused_frame->SelectRange(blink::WebRange(range.StartOffset() + start,
+                                             range.length() + end - start),
+                             blink::WebLocalFrame::kPreserveHandleVisibility,
+                             selection_menu_behavior);
+}
+
+void WebFrameWidgetImpl::MoveRangeSelectionExtent(
+    const gfx::Point& extent_in_dips) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->MoveRangeSelectionExtent(
+      widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
+}
+
+void WebFrameWidgetImpl::ScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& rect_in_dips) {
+  WebLocalFrame* local_frame = FocusedWebLocalFrameInWidget();
+  if (!local_frame)
+    return;
+
+  // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
+  // on OOPIFs. Since we are starting a new scroll operation now, call
+  // DidChangeVisibleViewport to ensure that we don't assume the element
+  // is already in view and ignore the scroll.
+  local_frame->Client()->ResetHasScrolledFocusedEditableIntoView();
+  local_frame->Client()->ScrollFocusedEditableElementIntoRect(rect_in_dips);
+}
+
+void WebFrameWidgetImpl::ZoomToFindInPageRect(
+    const WebRect& rect_in_root_frame) {
+  if (ForMainFrame()) {
+    View()->ZoomToFindInPageRect(rect_in_root_frame);
+  } else {
+    GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
+        gfx::Rect(rect_in_root_frame));
+  }
+}
+
+void WebFrameWidgetImpl::MoveCaret(const gfx::Point& point_in_dips) {
+  WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame)
+    return;
+  focused_frame->MoveCaretSelection(
+      widget_base_->DIPsToRoundedBlinkSpace(point_in_dips));
+}
+
+#if defined(OS_ANDROID)
+void WebFrameWidgetImpl::SelectWordAroundCaret(
+    SelectWordAroundCaretCallback callback) {
+  auto* focused_frame = FocusedWebLocalFrameInWidget();
+  if (!focused_frame) {
+    std::move(callback).Run(false, 0, 0);
+    return;
+  }
+
+  bool did_select = false;
+  int start_adjust = 0;
+  int end_adjust = 0;
+  blink::WebRange initial_range = focused_frame->SelectionRange();
+  SetHandlingInputEvent(true);
+  if (!initial_range.IsNull())
+    did_select = focused_frame->SelectWordAroundCaret();
+  if (did_select) {
+    blink::WebRange adjusted_range = focused_frame->SelectionRange();
+    DCHECK(!adjusted_range.IsNull());
+    start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset();
+    end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
+  }
+  SetHandlingInputEvent(false);
+  std::move(callback).Run(did_select, start_adjust, end_adjust);
+}
+#endif
+
+void WebFrameWidgetImpl::ForEachRemoteFrameControlledByWidget(
+    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+  ForEachRemoteFrameChildrenControlledByWidget(local_root_->GetFrame(),
+                                               callback);
+}
+
+void WebFrameWidgetImpl::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
+                                                  gfx::Rect& focus_root_frame) {
+  const LocalFrame* local_frame = FocusedLocalFrameInWidget();
+  if (!local_frame)
+    return;
+
+  IntRect anchor;
+  IntRect focus;
+  if (!local_frame->Selection().ComputeAbsoluteBounds(anchor, focus))
+    return;
+
+  // Apply the visual viewport for main frames this will apply the page scale.
+  // For subframes it will just be a 1:1 transformation and the browser
+  // will then apply later transformations to these rects.
+  VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
+  anchor_root_frame = visual_viewport.RootFrameToViewport(
+      local_frame->View()->ConvertToRootFrame(anchor));
+  focus_root_frame = visual_viewport.RootFrameToViewport(
+      local_frame->View()->ConvertToRootFrame(focus));
+}
+
+void WebFrameWidgetImpl::BatterySavingsChanged(WebBatterySavingsFlags savings) {
+  widget_base_->LayerTreeHost()->SetEnableFrameRateThrottling(
+      savings & kAllowReducedFrameRate);
+}
+
+const viz::LocalSurfaceId& WebFrameWidgetImpl::LocalSurfaceIdFromParent() {
+  return widget_base_->local_surface_id_from_parent();
+}
+
+cc::LayerTreeHost* WebFrameWidgetImpl::LayerTreeHost() {
+  return widget_base_->LayerTreeHost();
+}
+
+ScreenMetricsEmulator* WebFrameWidgetImpl::DeviceEmulator() {
+  return device_emulator_;
+}
+
+bool WebFrameWidgetImpl::AutoResizeMode() {
+  return View()->AutoResizeMode();
+}
+
+void WebFrameWidgetImpl::SetScreenMetricsEmulationParameters(
+    bool enabled,
+    const DeviceEmulationParams& params) {
+  if (enabled)
+    View()->ActivateDevToolsTransform(params);
+  else
+    View()->DeactivateDevToolsTransform();
+}
+
+void WebFrameWidgetImpl::SetScreenInfoAndSize(
+    const ScreenInfo& screen_info,
+    const gfx::Size& widget_size_in_dips,
+    const gfx::Size& visible_viewport_size_in_dips) {
+  // Emulation happens on regular main frames which don't use auto-resize mode.
+  DCHECK(!AutoResizeMode());
+
+  UpdateScreenInfo(screen_info);
+  widget_base_->SetVisibleViewportSizeInDIPs(visible_viewport_size_in_dips);
+  Resize(widget_base_->DIPsToCeiledBlinkSpace(widget_size_in_dips));
+}
+
+void WebFrameWidgetImpl::NotifyPageScaleFactorChanged(
+    float page_scale_factor,
+    bool is_pinch_gesture_active) {
+  // Store the value to give to any new RemoteFrame that will be created as a
+  // descendant of this widget.
+  page_scale_factor_in_mainframe_ = page_scale_factor;
+  is_pinch_gesture_active_in_mainframe_ = is_pinch_gesture_active;
+  // Push the page scale factor down to any child RemoteFrames.
+  // TODO(danakj): This ends up setting the page scale factor in the
+  // RenderWidgetHost of the child WebFrameWidgetImpl, so that it can bounce
+  // the value down to its WebFrameWidgetImpl. Since this is essentially a
+  // global value per-page, we could instead store it once in the browser
+  // (such as in RenderViewHost) and distribute it to each WebFrameWidgetImpl
+  // from there.
+  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+      [](float page_scale_factor, bool is_pinch_gesture_active,
+         RemoteFrame* remote_frame) {
+        remote_frame->Client()->PageScaleFactorChanged(page_scale_factor,
+                                                       is_pinch_gesture_active);
+      },
+      page_scale_factor, is_pinch_gesture_active));
+}
+
+void WebFrameWidgetImpl::SetPageScaleStateAndLimits(
+    float page_scale_factor,
+    bool is_pinch_gesture_active,
+    float minimum,
+    float maximum) {
+  widget_base_->LayerTreeHost()->SetPageScaleFactorAndLimits(page_scale_factor,
+                                                             minimum, maximum);
+
+  // Only propagate page scale from the main frame.
+  if (ForMainFrame()) {
+    // If page scale hasn't changed, then just return without notifying
+    // the remote frames.
+    if (page_scale_factor == page_scale_factor_in_mainframe_ &&
+        is_pinch_gesture_active == is_pinch_gesture_active_in_mainframe_) {
+      return;
+    }
+
+    NotifyPageScaleFactorChanged(page_scale_factor, is_pinch_gesture_active);
+  }
+}
+
+bool WebFrameWidgetImpl::UpdateScreenRects(
+    const gfx::Rect& widget_screen_rect,
+    const gfx::Rect& window_screen_rect) {
+  if (!device_emulator_)
+    return false;
+  device_emulator_->OnUpdateScreenRects(widget_screen_rect, window_screen_rect);
+  return true;
+}
+
+void WebFrameWidgetImpl::OrientationChanged() {
+  local_root_->SendOrientationChangeEvent();
+}
+
+void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
+    const ScreenInfo& previous_original_screen_info) {
+  ScreenInfo screen_info = widget_base_->GetScreenInfo();
+  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+    View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
+  } else {
+    View()->SetDeviceScaleFactor(screen_info.device_scale_factor);
+  }
+
+  if (Client()->ShouldAutoDetermineCompositingToLCDTextSetting()) {
+    // This causes compositing state to be modified which dirties the
+    // document lifecycle. Android Webview relies on the document
+    // lifecycle being clean after the RenderWidget is initialized, in
+    // order to send IPCs that query and change compositing state. So
+    // WebFrameWidgetImpl::Resize() must come after this call, as it runs the
+    // entire document lifecycle.
+    View()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
+        widget_base_->ComputePreferCompositingToLCDText());
+  }
+
+  // When the device scale changes, the size and position of the popup would
+  // need to be adjusted, which we can't do. Just close the popup, which is
+  // also consistent with page zoom and resize behavior.
+  if (previous_original_screen_info.device_scale_factor !=
+      screen_info.device_scale_factor) {
+    View()->CancelPagePopup();
+  }
+
+  // Propagate changes down to child local root RenderWidgets and BrowserPlugins
+  // in other frame trees/processes.
+  ScreenInfo original_screen_info = GetOriginalScreenInfo();
+  if (previous_original_screen_info != original_screen_info) {
+    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
+        [](const ScreenInfo& original_screen_info, RemoteFrame* remote_frame) {
+          remote_frame->Client()->DidChangeScreenInfo(original_screen_info);
+        },
+        original_screen_info));
+  }
+}
+
+gfx::Rect WebFrameWidgetImpl::ViewportVisibleRect() {
+  if (ForMainFrame()) {
+    return widget_base_->CompositorViewportRect();
+  } else {
+    return child_data().compositor_visible_rect;
+  }
+}
+
+const ScreenInfo& WebFrameWidgetImpl::GetOriginalScreenInfo() {
+  if (device_emulator_)
+    return device_emulator_->original_screen_info();
+  return widget_base_->GetScreenInfo();
+}
+
+base::Optional<blink::mojom::ScreenOrientation>
+WebFrameWidgetImpl::ScreenOrientationOverride() {
+  return View()->ScreenOrientationOverride();
+}
+
+void WebFrameWidgetImpl::WasHidden() {
+  ForEachLocalFrameControlledByWidget(
+      local_root_->GetFrame(),
+      WTF::BindRepeating([](WebLocalFrame* local_frame) {
+        local_frame->Client()->WasHidden();
+      }));
+}
+
+void WebFrameWidgetImpl::WasShown(bool was_evicted) {
+  ForEachLocalFrameControlledByWidget(
+      local_root_->GetFrame(),
+      WTF::BindRepeating([](WebLocalFrame* local_frame) {
+        local_frame->Client()->WasShown();
+      }));
+  if (was_evicted) {
+    ForEachRemoteFrameControlledByWidget(
+        WTF::BindRepeating([](RemoteFrame* remote_frame) {
+          remote_frame->Client()->WasEvicted();
+        }));
+  }
+}
+
+void WebFrameWidgetImpl::RunPaintBenchmark(int repeat_count,
+                                           cc::PaintBenchmarkResult& result) {
+  if (!ForMainFrame())
+    return;
+  if (auto* frame_view = LocalRootImpl()->GetFrameView())
+    frame_view->RunPaintBenchmark(repeat_count, result);
+}
+
+void WebFrameWidgetImpl::NotifyInputObservers(
+    const WebCoalescedInputEvent& coalesced_event) {
+  LocalFrame* frame = FocusedLocalFrameInWidget();
+  if (!frame)
+    return;
+
+  LocalFrameView* frame_view = frame->View();
+  if (!frame_view)
+    return;
+
+  const WebInputEvent& input_event = coalesced_event.Event();
+  auto& paint_timing_detector = frame_view->GetPaintTimingDetector();
+
+  if (paint_timing_detector.NeedToNotifyInputOrScroll())
+    paint_timing_detector.NotifyInputEvent(input_event.GetType());
+}
+
+Frame* WebFrameWidgetImpl::FocusedCoreFrame() const {
+  return GetPage() ? GetPage()->GetFocusController().FocusedOrMainFrame()
+                   : nullptr;
+}
+
+Element* WebFrameWidgetImpl::FocusedElement() const {
+  LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
+  if (!frame)
+    return nullptr;
+
+  Document* document = frame->GetDocument();
+  if (!document)
+    return nullptr;
+
+  return document->FocusedElement();
+}
+
+HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
+    const FloatPoint& pos_in_root_frame) {
+  FloatPoint doc_point =
+      LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
+          pos_in_root_frame);
+  HitTestLocation location(doc_point);
+  HitTestResult result =
+      LocalRootImpl()->GetFrame()->View()->HitTestWithThrottlingAllowed(
+          location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+  result.SetToShadowHostIfInRestrictedShadowRoot();
+  return result;
+}
+
+bool WebFrameWidgetImpl::SynchronousResizeModeForTestingEnabled() {
+  return main_data().synchronous_resize_mode_for_testing;
+}
+
+KURL WebFrameWidgetImpl::GetURLForDebugTrace() {
+  WebFrame* main_frame = View()->MainFrame();
+  if (main_frame->IsWebLocalFrame())
+    return main_frame->ToWebLocalFrame()->GetDocument().Url();
+  return {};
+}
+
+float WebFrameWidgetImpl::GetTestingDeviceScaleFactorOverride() {
+  return device_scale_factor_for_testing_;
+}
+
+void WebFrameWidgetImpl::ReleaseMouseLockAndPointerCaptureForTesting() {
+  GetPage()->GetPointerLockController().ExitPointerLock();
+  MouseCaptureLost();
+}
+
+const viz::FrameSinkId& WebFrameWidgetImpl::GetFrameSinkId() {
+  // It is valid to create a WebFrameWidget with an invalid frame sink id for
+  // printing and placeholders. But if we go to use it, it should be valid.
+  DCHECK(frame_sink_id_.is_valid());
+  return frame_sink_id_;
+}
+
+WebHitTestResult WebFrameWidgetImpl::HitTestResultAt(const gfx::PointF& point) {
+  return CoreHitTestResultAt(point);
+}
+
+void WebFrameWidgetImpl::SetZoomLevelForTesting(double zoom_level) {
+  DCHECK(ForMainFrame());
+  DCHECK_NE(zoom_level, -INFINITY);
+  zoom_level_for_testing_ = zoom_level;
+  SetZoomLevel(zoom_level);
+}
+
+void WebFrameWidgetImpl::ResetZoomLevelForTesting() {
+  DCHECK(ForMainFrame());
+  zoom_level_for_testing_ = -INFINITY;
+  SetZoomLevel(0);
+}
+
+void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
+  DCHECK(ForMainFrame());
+  DCHECK_GE(factor, 0.f);
+
+  // Stash the window size before we adjust the scale factor, as subsequent
+  // calls to convert will use the new scale factor.
+  gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
+  device_scale_factor_for_testing_ = factor;
+
+  // Receiving a 0 is used to reset between tests, it removes the override in
+  // order to listen to the browser for the next test.
+  if (!factor)
+    return;
+
+  // We are changing the device scale factor from the renderer, so allocate a
+  // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+  ScreenInfo info = widget_base_->GetScreenInfo();
+  info.device_scale_factor = factor;
+  gfx::Size size_with_dsf = gfx::ScaleToCeiledSize(size_in_dips, factor);
+  widget_base_->UpdateCompositorViewportAndScreenInfo(gfx::Rect(size_with_dsf),
+                                                      info);
+  if (!AutoResizeMode()) {
+    // This picks up the new device scale factor as
+    // `UpdateCompositorViewportAndScreenInfo()` has applied a new value.
+    Resize(widget_base_->DIPsToCeiledBlinkSpace(size_in_dips));
+  }
+}
+
+WebPlugin* WebFrameWidgetImpl::GetFocusedPluginContainer() {
+  LocalFrame* focused_frame = FocusedLocalFrameInWidget();
+  if (!focused_frame)
+    return nullptr;
+  if (auto* container = focused_frame->GetWebPluginContainer())
+    return container->Plugin();
+  return nullptr;
+}
+
+bool WebFrameWidgetImpl::CanComposeInline() {
+  if (auto* plugin = GetFocusedPluginContainer())
+    return plugin->CanComposeInline();
+  return true;
+}
+
+bool WebFrameWidgetImpl::ShouldDispatchImeEventsToPlugin() {
+  if (auto* plugin = GetFocusedPluginContainer())
+    return plugin->ShouldDispatchImeEventsToPlugin();
+  return false;
+}
+
+void WebFrameWidgetImpl::ImeSetCompositionForPlugin(
+    const String& text,
+    const Vector<ui::ImeTextSpan>& ime_text_spans,
+    const gfx::Range& replacement_range,
+    int selection_start,
+    int selection_end) {
+  if (auto* plugin = GetFocusedPluginContainer()) {
+    plugin->ImeSetCompositionForPlugin(
+        text,
+        std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
+                                     ime_text_spans.end()),
+        replacement_range, selection_start, selection_end);
+  }
+}
+
+void WebFrameWidgetImpl::ImeCommitTextForPlugin(
+    const String& text,
+    const Vector<ui::ImeTextSpan>& ime_text_spans,
+    const gfx::Range& replacement_range,
+    int relative_cursor_pos) {
+  if (auto* plugin = GetFocusedPluginContainer()) {
+    plugin->ImeCommitTextForPlugin(
+        text,
+        std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
+                                     ime_text_spans.end()),
+        replacement_range, relative_cursor_pos);
+  }
+}
+
+void WebFrameWidgetImpl::ImeFinishComposingTextForPlugin(bool keep_selection) {
+  if (auto* plugin = GetFocusedPluginContainer())
+    plugin->ImeFinishComposingTextForPlugin(keep_selection);
+}
+
+void WebFrameWidgetImpl::SetWindowRect(const gfx::Rect& window_rect) {
+  DCHECK(ForMainFrame());
+  if (SynchronousResizeModeForTestingEnabled()) {
+    // This is a web-test-only path. At one point, it was planned to be
+    // removed. See https://crbug.com/309760.
+    SetWindowRectSynchronously(window_rect);
+    return;
+  }
+
+  SetPendingWindowRect(window_rect);
+  View()->SendWindowRectToMainFrameHost(
+      window_rect, WTF::Bind(&WebFrameWidgetImpl::AckPendingWindowRect,
+                             WrapWeakPersistent(this)));
+}
+
+void WebFrameWidgetImpl::SetWindowRectSynchronouslyForTesting(
+    const gfx::Rect& new_window_rect) {
+  DCHECK(ForMainFrame());
+  SetWindowRectSynchronously(new_window_rect);
+}
+
+void WebFrameWidgetImpl::SetWindowRectSynchronously(
+    const gfx::Rect& new_window_rect) {
+  // This method is only call in tests, and it applies the |new_window_rect| to
+  // all three of:
+  // a) widget size (in |size_|)
+  // b) blink viewport (in |visible_viewport_size_|)
+  // c) compositor viewport (in cc::LayerTreeHost)
+  // Normally the browser controls these three things independently, but this is
+  // used in tests to control the size from the renderer.
+
+  // We are resizing the window from the renderer, so allocate a new
+  // viz::LocalSurfaceId to avoid surface invariants violations in tests.
+  widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
+
+  gfx::Rect compositor_viewport_pixel_rect(gfx::ScaleToCeiledSize(
+      new_window_rect.size(),
+      widget_base_->GetScreenInfo().device_scale_factor));
+  widget_base_->UpdateSurfaceAndScreenInfo(
+      widget_base_->local_surface_id_from_parent(),
+      compositor_viewport_pixel_rect, widget_base_->GetScreenInfo());
+
+  Resize(new_window_rect.size());
+  widget_base_->SetScreenRects(new_window_rect, new_window_rect);
+}
+
+void WebFrameWidgetImpl::DidCreateLocalRootView() {
+  // If this WebWidget still hasn't received its size from the embedder, block
+  // the parser. This is necessary, because the parser can cause layout to
+  // happen, which needs to be done with the correct size.
+  if (ForSubframe() && !size_) {
+    child_data().did_suspend_parsing = true;
+    LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->BlockParser();
+  }
+}
+
+mojom::blink::ScrollIntoViewParamsPtr
+WebFrameWidgetImpl::GetScrollParamsForFocusedEditableElement(
+    const Element& element,
+    PhysicalRect& out_rect_to_scroll) {
+  // For main frames, scrolling takes place in two phases.
+  if (ForMainFrame()) {
+    // Since the page has been resized, the layout may have changed. The page
+    // scale animation started by ZoomAndScrollToFocusedEditableRect will scroll
+    // only the visual and layout viewports. We'll call ScrollRectToVisible with
+    // the stop_at_main_frame_layout_viewport param to ensure the element is
+    // actually visible in the page.
+    mojom::blink::ScrollIntoViewParamsPtr params =
+        ScrollAlignment::CreateScrollIntoViewParams(
+            ScrollAlignment::CenterIfNeeded(),
+            ScrollAlignment::CenterIfNeeded(),
+            mojom::blink::ScrollType::kProgrammatic, false,
+            mojom::blink::ScrollBehavior::kInstant);
+    params->stop_at_main_frame_layout_viewport = true;
+    out_rect_to_scroll =
+        PhysicalRect(element.GetLayoutObject()->AbsoluteBoundingBoxRect());
+    return params;
+  }
+
+  LocalFrameView& frame_view = *element.GetDocument().View();
+  IntRect absolute_element_bounds =
+      element.GetLayoutObject()->AbsoluteBoundingBoxRect();
+  IntRect absolute_caret_bounds =
+      element.GetDocument().GetFrame()->Selection().AbsoluteCaretBounds();
+  // Ideally, the chosen rectangle includes the element box and caret bounds
+  // plus some margin on the left. If this does not work (i.e., does not fit
+  // inside the frame view), then choose a subrect which includes the caret
+  // bounds. It is preferable to also include element bounds' location and left
+  // align the scroll. If this cant be satisfied, the scroll will be right
+  // aligned.
+  IntRect maximal_rect =
+      UnionRect(absolute_element_bounds, absolute_caret_bounds);
+
+  // Set the ideal margin.
+  maximal_rect.ShiftXEdgeTo(
+      maximal_rect.X() -
+      static_cast<int>(kIdealPaddingRatio * absolute_element_bounds.Width()));
+
+  bool maximal_rect_fits_in_frame =
+      !(frame_view.Size() - maximal_rect.Size()).IsEmpty();
+
+  if (!maximal_rect_fits_in_frame) {
+    IntRect frame_rect(maximal_rect.Location(), frame_view.Size());
+    maximal_rect.Intersect(frame_rect);
+    IntPoint point_forced_to_be_visible =
+        absolute_caret_bounds.MaxXMaxYCorner() +
+        IntSize(kCaretPadding, kCaretPadding);
+    if (!maximal_rect.Contains(point_forced_to_be_visible)) {
+      // Move the rect towards the point until the point is barely contained.
+      maximal_rect.Move(point_forced_to_be_visible -
+                        maximal_rect.MaxXMaxYCorner());
+    }
+  }
+
+  mojom::blink::ScrollIntoViewParamsPtr params =
+      ScrollAlignment::CreateScrollIntoViewParams();
+  params->zoom_into_rect = View()->ShouldZoomToLegibleScale(element);
+  params->relative_element_bounds = NormalizeRect(
+      Intersection(absolute_element_bounds, maximal_rect), maximal_rect);
+  params->relative_caret_bounds = NormalizeRect(
+      Intersection(absolute_caret_bounds, maximal_rect), maximal_rect);
+  params->behavior = mojom::blink::ScrollBehavior::kInstant;
+  out_rect_to_scroll = PhysicalRect(maximal_rect);
+  return params;
+}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index 084aea6..bd958df 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -31,34 +31,74 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_IMPL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_IMPL_H_
 
-#include <memory>
-
-#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/types/pass_key.h"
+#include "build/build_config.h"
+#include "cc/input/event_listener_properties.h"
+#include "cc/input/layer_selection_bound.h"
+#include "cc/input/overscroll_behavior.h"
+#include "cc/trees/layer_tree_host.h"
+#include "services/viz/public/mojom/hit_test/input_target_client.mojom-blink.h"
 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/public/web/web_input_method_controller.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+#include "third_party/blink/public/common/input/web_gesture_device.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h"
+#include "third_party/blink/public/mojom/page/drag.mojom-blink.h"
+#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
+#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
+#include "third_party/blink/public/platform/web_battery_savings.h"
+#include "third_party/blink/public/platform/web_drag_data.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
+#include "third_party/blink/public/web/web_meaningful_layout.h"
+#include "third_party/blink/renderer/core/clipboard/data_object.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
+#include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
+#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
 #include "third_party/blink/renderer/platform/graphics/apply_viewport_changes.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/widget/frame_widget.h"
+#include "third_party/blink/renderer/platform/widget/widget_base_client.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "ui/base/mojom/ui_base_types.mojom-shared.h"
+
+namespace gfx {
+class Point;
+class PointF;
+}  // namespace gfx
 
 namespace blink {
-class WebFrameWidget;
-class WebFrameWidgetImpl;
+class AnimationWorkletMutatorDispatcherImpl;
+class FloatPoint;
+class HitTestResult;
+class HTMLPlugInElement;
+class Page;
+class PageWidgetEventHandler;
+class PaintWorkletPaintDispatcher;
+class RemoteFrame;
+class WebLocalFrameImpl;
+class WebPlugin;
+class WebViewImpl;
+class WidgetBase;
+class ScreenMetricsEmulator;
 
-// Implements WebFrameWidget for a child local root frame (OOPIF). This object
-// is created in the child renderer and attached to the OOPIF's WebLocalFrame.
-//
-// For the main frame's WebFrameWidget implementation, see WebViewFrameWidget.
-//
-class WebFrameWidgetImpl final : public WebFrameWidgetBase {
+// Implements WebFrameWidget for both main frames and child local root frame
+// (OOPIF).
+class CORE_EXPORT WebFrameWidgetImpl
+    : public GarbageCollected<WebFrameWidgetImpl>,
+      public WebFrameWidget,
+      public WidgetBaseClient,
+      public mojom::blink::FrameWidget,
+      public viz::mojom::blink::InputTargetClient,
+      public FrameWidget,
+      public PageWidgetEventHandler {
  public:
   WebFrameWidgetImpl(
       base::PassKey<WebFrameWidget>,
@@ -74,13 +114,919 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       const viz::FrameSinkId& frame_sink_id,
       bool hidden,
-      bool never_composited);
+      bool never_composited,
+      bool is_for_child_local_root,
+      bool is_for_nested_main_frame);
   ~WebFrameWidgetImpl() override;
 
+  virtual void Trace(Visitor*) const;
+
+  // Returns the WebFrame that this widget is attached to. It will be a local
+  // root since only local roots have a widget attached.
+  WebLocalFrameImpl* LocalRootImpl() const { return local_root_; }
+
+  // Returns the bounding box of the block type node touched by the WebPoint.
+  WebRect ComputeBlockBound(const gfx::Point& point_in_root_frame,
+                            bool ignore_clipping) const;
+
+  void BindLocalRoot(WebLocalFrame&);
+
+  // If this widget is for the top most main frame. This is different than
+  // |ForMainFrame| because |ForMainFrame| could return true but this method
+  // returns false. If this widget is a MainFrame widget embedded in another
+  // widget, for example embedding a portal.
+  bool ForTopMostMainFrame() const;
+
+  // Adjusts whether the widget is nested or not. This is called during portal
+  // transitions.
+  void SetIsNestedMainFrameWidget(bool is_nested);
+
+  // Returns true if this widget is for a local root that is a child frame,
+  // false otherwise.
+  bool ForSubframe() const { return is_for_child_local_root_; }
+
+  // Opposite of |ForSubframe|. If this widget is for the local main frame.
+  bool ForMainFrame() const { return !ForSubframe(); }
+
+  // Called when the intrinsic size of the owning container is changing its
+  // size. This should only be called when `ForSubframe` is true.
+  void IntrinsicSizingInfoChanged(mojom::blink::IntrinsicSizingInfoPtr);
+
+  void AutoscrollStart(const gfx::PointF& position);
+  void AutoscrollFling(const gfx::Vector2dF& position);
+  void AutoscrollEnd();
+
+  bool HandleCurrentKeyboardEvent();
+
+  // Creates or returns cached mutator dispatcher. This usually requires a
+  // round trip to the compositor. The returned WeakPtr must only be
+  // dereferenced on the output |mutator_task_runner|.
+  base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
+  EnsureCompositorMutatorDispatcher(
+      scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner);
+
+  // TODO: consider merge the input and return value to be one parameter.
+  // Creates or returns cached paint dispatcher. The returned WeakPtr must only
+  // be dereferenced on the output |paint_task_runner|.
+  base::WeakPtr<PaintWorkletPaintDispatcher> EnsureCompositorPaintDispatcher(
+      scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner);
+
+  HitTestResult CoreHitTestResultAt(const gfx::PointF&);
+
+  // FrameWidget overrides:
+  WebWidgetClient* Client() const final { return client_; }
+  cc::AnimationHost* AnimationHost() const final;
+  void SetOverscrollBehavior(
+      const cc::OverscrollBehavior& overscroll_behavior) final;
+  void RequestAnimationAfterDelay(const base::TimeDelta&) final;
+  void SetRootLayer(scoped_refptr<cc::Layer>) override;
+  void RegisterSelection(cc::LayerSelection selection) final;
+  void RequestDecode(const cc::PaintImage&,
+                     base::OnceCallback<void(bool)>) final;
+  void NotifySwapAndPresentationTimeInBlink(
+      WebReportTimeCallback swap_callback,
+      WebReportTimeCallback presentation_callback) final;
+  void RequestBeginMainFrameNotExpected(bool request) final;
+  int GetLayerTreeId() final;
+  void SetEventListenerProperties(cc::EventListenerClass,
+                                  cc::EventListenerProperties) final;
+  cc::EventListenerProperties EventListenerProperties(
+      cc::EventListenerClass) const final;
+  mojom::blink::DisplayMode DisplayMode() const override;
+  const WebVector<gfx::Rect>& WindowSegments() const override;
+  void SetDelegatedInkMetadata(
+      std::unique_ptr<viz::DelegatedInkMetadata> metadata) final;
+  void DidOverscroll(const gfx::Vector2dF& overscroll_delta,
+                     const gfx::Vector2dF& accumulated_overscroll,
+                     const gfx::PointF& position,
+                     const gfx::Vector2dF& velocity) override;
+  void InjectGestureScrollEvent(WebGestureDevice device,
+                                const gfx::Vector2dF& delta,
+                                ui::ScrollGranularity granularity,
+                                cc::ElementId scrollable_area_element_id,
+                                WebInputEvent::Type injected_type) override;
+  void DidChangeCursor(const ui::Cursor&) override;
+  void GetCompositionCharacterBoundsInWindow(
+      Vector<gfx::Rect>* bounds_in_dips) override;
+  gfx::Range CompositionRange() override;
+  WebTextInputInfo TextInputInfo() override;
+  ui::mojom::VirtualKeyboardVisibilityRequest
+  GetLastVirtualKeyboardVisibilityRequest() override;
+  bool ShouldSuppressKeyboardForFocusedElement() override;
+  void GetEditContextBoundsInWindow(
+      base::Optional<gfx::Rect>* control_bounds,
+      base::Optional<gfx::Rect>* selection_bounds) override;
+  int32_t ComputeWebTextInputNextPreviousFlags() override;
+  void ResetVirtualKeyboardVisibilityRequest() override;
+  bool GetSelectionBoundsInWindow(gfx::Rect* focus,
+                                  gfx::Rect* anchor,
+                                  base::i18n::TextDirection* focus_dir,
+                                  base::i18n::TextDirection* anchor_dir,
+                                  bool* is_anchor_first) override;
+  void ClearTextInputState() override;
+
+  bool SetComposition(const String& text,
+                      const Vector<ui::ImeTextSpan>& ime_text_spans,
+                      const gfx::Range& replacement_range,
+                      int selection_start,
+                      int selection_end) override;
+  void CommitText(const String& text,
+                  const Vector<ui::ImeTextSpan>& ime_text_spans,
+                  const gfx::Range& replacement_range,
+                  int relative_cursor_pos) override;
+  void FinishComposingText(bool keep_selection) override;
+  bool IsProvisional() override;
+  uint64_t GetScrollableContainerIdAt(
+      const gfx::PointF& point_in_dips) override;
+  bool ShouldHandleImeEvents() override;
+  void SetEditCommandsForNextKeyEvent(
+      Vector<mojom::blink::EditCommandPtr> edit_commands) override;
+
+  void AddImeTextSpansToExistingText(
+      uint32_t start,
+      uint32_t end,
+      const Vector<ui::ImeTextSpan>& ime_text_spans) override;
+  Vector<ui::mojom::blink::ImeTextSpanInfoPtr> GetImeTextSpansInfo(
+      const WebVector<ui::ImeTextSpan>& ime_text_spans) override;
+  void ClearImeTextSpansByType(uint32_t start,
+                               uint32_t end,
+                               ui::ImeTextSpan::Type type) override;
+  void SetCompositionFromExistingText(
+      int32_t start,
+      int32_t end,
+      const Vector<ui::ImeTextSpan>& ime_text_spans) override;
+  void ExtendSelectionAndDelete(int32_t before, int32_t after) override;
+  void DeleteSurroundingText(int32_t before, int32_t after) override;
+  void DeleteSurroundingTextInCodePoints(int32_t before,
+                                         int32_t after) override;
+  void SetEditableSelectionOffsets(int32_t start, int32_t end) override;
+  void ExecuteEditCommand(const String& command, const String& value) override;
+  void Undo() override;
+  void Redo() override;
+  void Cut() override;
+  void Copy() override;
+  void CopyToFindPboard() override;
+  void Paste() override;
+  void PasteAndMatchStyle() override;
+  void Delete() override;
+  void SelectAll() override;
+  void CollapseSelection() override;
+  void Replace(const String& word) override;
+  void ReplaceMisspelling(const String& word) override;
+  void SelectRange(const gfx::Point& base_in_dips,
+                   const gfx::Point& extent_in_dips) override;
+  void AdjustSelectionByCharacterOffset(
+      int32_t start,
+      int32_t end,
+      mojom::blink::SelectionMenuBehavior behavior) override;
+  void MoveRangeSelectionExtent(const gfx::Point& extent_in_dips) override;
+  void ScrollFocusedEditableNodeIntoRect(
+      const gfx::Rect& rect_in_dips) override;
+  void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override;
+  void MoveCaret(const gfx::Point& point_in_dips) override;
+#if defined(OS_ANDROID)
+  void SelectWordAroundCaret(SelectWordAroundCaretCallback callback) override;
+#endif
+  gfx::RectF BlinkSpaceToDIPs(const gfx::RectF& rect) override;
+  gfx::Rect BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) override;
+  gfx::Size BlinkSpaceToFlooredDIPs(const gfx::Size& size) override;
+  gfx::RectF DIPsToBlinkSpace(const gfx::RectF& rect) override;
+  gfx::PointF DIPsToBlinkSpace(const gfx::PointF& point) override;
+  gfx::Point DIPsToRoundedBlinkSpace(const gfx::Point& point) override;
+  float DIPsToBlinkSpace(float scalar) override;
+  void RequestMouseLock(
+      bool has_transient_user_activation,
+      bool request_unadjusted_movement,
+      mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback)
+      override;
+  void MouseCaptureLost() override;
+  bool CanComposeInline() override;
+  bool ShouldDispatchImeEventsToPlugin() override;
+  void ImeSetCompositionForPlugin(const String& text,
+                                  const Vector<ui::ImeTextSpan>& ime_text_spans,
+                                  const gfx::Range& replacement_range,
+                                  int selection_start,
+                                  int selection_end) override;
+  void ImeCommitTextForPlugin(const String& text,
+                              const Vector<ui::ImeTextSpan>& ime_text_spans,
+                              const gfx::Range& replacement_range,
+                              int relative_cursor_pos) override;
+  void ImeFinishComposingTextForPlugin(bool keep_selection) override;
+
+  // WebFrameWidget implementation.
+  WebLocalFrame* LocalRoot() const override;
+  void SendOverscrollEventFromImplSide(
+      const gfx::Vector2dF& overscroll_delta,
+      cc::ElementId scroll_latched_element_id) override;
+  void SendScrollEndEventFromImplSide(
+      cc::ElementId scroll_latched_element_id) override;
+  WebInputMethodController* GetActiveWebInputMethodController() const override;
+  WebLocalFrame* FocusedWebLocalFrameInWidget() const override;
+  bool ScrollFocusedEditableElementIntoView() override;
+  void ApplyViewportChangesForTesting(
+      const ApplyViewportChangesArgs& args) override;
+  void NotifySwapAndPresentationTime(
+      WebReportTimeCallback swap_callback,
+      WebReportTimeCallback presentation_callback) override;
+  scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
+      override;
+  void WaitForDebuggerWhenShown() override;
+  void SetTextZoomFactor(float text_zoom_factor) override;
+  float TextZoomFactor() override;
+  void SetMainFrameOverlayColor(SkColor) override;
+  void AddEditCommandForNextKeyEvent(const WebString& name,
+                                     const WebString& value) override;
+  void ClearEditCommands() override;
+  bool IsPasting() override;
+  bool HandlingSelectRange() override;
+  void ReleaseMouseLockAndPointerCaptureForTesting() override;
+  const viz::FrameSinkId& GetFrameSinkId() override;
+  WebHitTestResult HitTestResultAt(const gfx::PointF&) override;
+  void SetZoomLevelForTesting(double zoom_level) override;
+  void ResetZoomLevelForTesting() override;
+  void SetDeviceScaleFactorForTesting(float factor) override;
+
+  // Called when a drag-n-drop operation should begin.
+  void StartDragging(const WebDragData&,
+                     DragOperationsMask,
+                     const SkBitmap& drag_image,
+                     const gfx::Point& drag_image_offset);
+
+  bool DoingDragAndDrop() { return doing_drag_and_drop_; }
+  static void SetIgnoreInputEvents(bool value) { ignore_input_events_ = value; }
+  static bool IgnoreInputEvents() { return ignore_input_events_; }
+
+  // Resets the layout tracking steps for the main frame. When
+  // `UpdateLifecycle()` is called it generates `WebMeaningfulLayout` events
+  // only once. This resets the state back to the default so it will fire new
+  // events.
+  void ResetMeaningfulLayoutStateForMainFrame();
+
+  // WebWidget overrides:
+  cc::LayerTreeHost* InitializeCompositing(
+      scheduler::WebThreadScheduler* main_thread_scheduler,
+      cc::TaskGraphRunner* task_graph_runner,
+      const ScreenInfo& screen_info,
+      std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
+      const cc::LayerTreeSettings* settings) override;
+  void Close(
+      scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) override;
+  void SetCompositorVisible(bool visible) override;
+  gfx::Size Size() override;
+  void Resize(const gfx::Size& size_with_dsf) override;
+  void SetCursor(const ui::Cursor& cursor) override;
+  bool HandlingInputEvent() override;
+  void SetHandlingInputEvent(bool handling) override;
+  void ProcessInputEventSynchronouslyForTesting(const WebCoalescedInputEvent&,
+                                                HandledEventCallback) override;
+  WebInputEventResult DispatchBufferedTouchEvents() override;
+  WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
+  void UpdateTextInputState() override;
+  void UpdateSelectionBounds() override;
+  void ShowVirtualKeyboard() override;
+  bool HasFocus() override;
+  void SetFocus(bool focus) override;
+  void FlushInputProcessedCallback() override;
+  void CancelCompositionForPepper() override;
+  void ApplyVisualProperties(
+      const VisualProperties& visual_properties) override;
+  bool PinchGestureActiveInMainFrame() override;
+  float PageScaleInMainFrame() override;
+  const ScreenInfo& GetScreenInfo() override;
+  gfx::Rect WindowRect() override;
+  gfx::Rect ViewRect() override;
+  void SetScreenRects(const gfx::Rect& widget_screen_rect,
+                      const gfx::Rect& window_screen_rect) override;
+  gfx::Size VisibleViewportSizeInDIPs() override;
+  bool IsHidden() const override;
+  WebString GetLastToolTipTextForTesting() const override;
+  float GetEmulatorScale() override;
+
+  // WidgetBaseClient overrides:
+  void BeginMainFrame(base::TimeTicks last_frame_time) override;
+  void UpdateLifecycle(WebLifecycleUpdate requested_update,
+                       DocumentUpdateReason reason) override;
+
+  // mojom::blink::FrameWidget overrides:
+  void ShowContextMenu(ui::mojom::MenuSourceType source_type,
+                       const gfx::Point& location) override;
+  void SetViewportIntersection(
+      mojom::blink::ViewportIntersectionStatePtr intersection_state) override;
+  void DragSourceEndedAt(const gfx::PointF& point_in_viewport,
+                         const gfx::PointF& screen_point,
+                         DragOperation) override;
+
+  // Sets the display mode, which comes from the top-level browsing context and
+  // is applied to all widgets.
+  void SetDisplayMode(mojom::blink::DisplayMode);
+
+  base::Optional<gfx::Point> GetAndResetContextMenuLocation();
+
+  void BindWidgetCompositor(
+      mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) override;
+
+  void BindInputTargetClient(
+      mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver)
+      override;
+
+  // viz::mojom::blink::InputTargetClient:
+  void FrameSinkIdAt(const gfx::PointF& point,
+                     const uint64_t trace_id,
+                     FrameSinkIdAtCallback callback) override;
+
+  // Called when the FrameView for this Widget's local root is created.
+  void DidCreateLocalRootView();
+
+  void SetZoomLevel(double zoom_level);
+
+  // Called when the View has auto resized.
+  void DidAutoResize(const gfx::Size& size);
+
+  // This method returns the focused frame belonging to this WebWidget, that
+  // is, a focused frame with the same local root as the one corresponding
+  // to this widget. It will return nullptr if no frame is focused or, the
+  // focused frame has a different local root.
+  LocalFrame* FocusedLocalFrameInWidget() const;
+
+  // For when the embedder itself change scales on the page (e.g. devtools)
+  // and wants all of the content at the new scale to be crisp
+  void SetNeedsRecalculateRasterScales();
+
+  // Sets the background color to be filled in as gutter behind/around the
+  // painted content. Non-composited WebViews need not implement this, as they
+  // paint into another widget which has a background color of its own.
+  void SetBackgroundColor(SkColor color);
+
+  // Starts an animation of the page scale to a target scale factor and scroll
+  // offset.
+  // If use_anchor is true, destination is a point on the screen that will
+  // remain fixed for the duration of the animation.
+  // If use_anchor is false, destination is the final top-left scroll position.
+  void StartPageScaleAnimation(const gfx::Vector2d& destination,
+                               bool use_anchor,
+                               float new_page_scale,
+                               base::TimeDelta duration);
+
+  // Called to update if scroll events should be sent.
+  void SetHaveScrollEventHandlers(bool);
+
+  // Start deferring commits to the compositor, allowing document lifecycle
+  // updates without committing the layer tree. Commits are deferred
+  // until at most the given |timeout| has passed. If multiple calls are made
+  // when deferral is active then the initial timeout applies.
+  void StartDeferringCommits(base::TimeDelta timeout);
+  // Immediately stop deferring commits.
+  void StopDeferringCommits(cc::PaintHoldingCommitTrigger);
+
+  // Prevents any updates to the input for the layer tree, and the layer tree
+  // itself, and the layer tree from becoming visible.
+  std::unique_ptr<cc::ScopedDeferMainFrameUpdate> DeferMainFrameUpdate();
+
+  // Sets the amount that the top and bottom browser controls are showing, from
+  // 0 (hidden) to 1 (fully shown).
+  void SetBrowserControlsShownRatio(float top_ratio, float bottom_ratio);
+
+  // Set browser controls params. These params consist of top and bottom
+  // heights, min-heights, browser_controls_shrink_blink_size, and
+  // animate_browser_controls_height_changes. If
+  // animate_browser_controls_height_changes is set to true, changes to the
+  // browser controls height will be animated. If
+  // browser_controls_shrink_blink_size is set to true, then Blink shrunk the
+  // viewport clip layers by the top and bottom browser controls height. Top
+  // controls will translate the web page down and do not immediately scroll
+  // when hiding. The bottom controls scroll immediately and never translate the
+  // content (only clip it).
+  void SetBrowserControlsParams(cc::BrowserControlsParams params);
+
+  cc::LayerTreeDebugState GetLayerTreeDebugState();
+  void SetLayerTreeDebugState(const cc::LayerTreeDebugState& state);
+
+  // Ask compositor to composite a frame for testing. This will generate a
+  // BeginMainFrame, and update the document lifecycle.
+  void SynchronouslyCompositeForTesting(base::TimeTicks frame_time);
+
+  // Adjust the synchronous resize mode for testing. Normally resizes are
+  // asynchronous with sending the resize to the browser, however some tests
+  // still need the resize to happen in a synchronous fashion.
+  void UseSynchronousResizeModeForTesting(bool enable);
+
+  // Sets the device color space for testing.
+  void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
+
+  // Converts from DIPs to Blink coordinate space (ie. Viewport/Physical
+  // pixels).
+  gfx::Size DIPsToCeiledBlinkSpace(const gfx::Size& size);
+
+  void SetWindowRect(const gfx::Rect& window_rect);
+  void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
+
+  void SetToolTipText(const String& tooltip_text, TextDirection dir);
+
+  void ShowVirtualKeyboardOnElementFocus();
+  void ProcessTouchAction(WebTouchAction touch_action);
+
+  // Called to update whether low latency input mode is enabled or not.
+  void SetNeedsLowLatencyInput(bool);
+
+  // Requests unbuffered (ie. low latency) input until a pointerup
+  // event occurs.
+  void RequestUnbufferedInputEvents();
+
+  // Requests unbuffered (ie. low latency) input due to debugger being
+  // attached. Debugger needs to paint when stopped in the event handler.
+  void SetNeedsUnbufferedInputForDebugger(bool);
+
+  // Called when the main frame navigates.
+  void DidNavigate();
+
+  // Called when the widget should get targeting input.
+  void SetMouseCapture(bool capture);
+
+  // Sets the current page scale factor and minimum / maximum limits. Both
+  // limits are initially 1 (no page scale allowed).
+  void SetPageScaleStateAndLimits(float page_scale_factor,
+                                  bool is_pinch_gesture_active,
+                                  float minimum,
+                                  float maximum);
+
+  // The value of the applied battery-savings META element in the document
+  // changed.
+  void BatterySavingsChanged(WebBatterySavingsFlags savings);
+
+  const viz::LocalSurfaceId& LocalSurfaceIdFromParent();
+  cc::LayerTreeHost* LayerTreeHost();
+
+  ScreenMetricsEmulator* DeviceEmulator();
+
+  // Calculates the selection bounds in the root frame. Returns bounds unchanged
+  // when there is no focused frame or no selection.
+  void CalculateSelectionBounds(gfx::Rect& anchor_in_root_frame,
+                                gfx::Rect& focus_in_root_frame);
+
+  // Returns if auto resize mode is enabled.
+  bool AutoResizeMode();
+
+  void SetScreenMetricsEmulationParameters(
+      bool enabled,
+      const blink::DeviceEmulationParams& params);
+  void SetScreenInfoAndSize(const blink::ScreenInfo& screen_info,
+                            const gfx::Size& widget_size,
+                            const gfx::Size& visible_viewport_size);
+
+  // Update the surface allocation information, compositor viewport rect and
+  // screen info on the widget.
+  void UpdateSurfaceAndScreenInfo(
+      const viz::LocalSurfaceId& new_local_surface_id,
+      const gfx::Rect& compositor_viewport_pixel_rect,
+      const ScreenInfo& new_screen_info);
+  // Similar to UpdateSurfaceAndScreenInfo but the surface allocation
+  // and compositor viewport rect remains the same.
+  void UpdateScreenInfo(const ScreenInfo& screen_info);
+  void UpdateSurfaceAndCompositorRect(
+      const viz::LocalSurfaceId& new_local_surface_id,
+      const gfx::Rect& compositor_viewport_pixel_rect);
+  void UpdateCompositorViewportRect(
+      const gfx::Rect& compositor_viewport_pixel_rect);
+  void SetWindowSegments(const std::vector<gfx::Rect>& window_segments);
+  viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point,
+                                         gfx::PointF* local_point);
+
+  // Set the pending window rect. For every SetPendingWindowRect
+  // call there must be an AckPendingWindowRect call.
+  void SetPendingWindowRect(const gfx::Rect& window_screen_rect);
+
+  // Clear a previously set pending window rect. For every SetPendingWindowRect
+  // call there must be an AckPendingWindowRect call.
+  void AckPendingWindowRect();
+
+  // Return the focused WebPlugin if there is one.
+  WebPlugin* GetFocusedPluginContainer();
+
  private:
-  friend class WebFrameWidget;  // For WebFrameWidget::create.
+  friend class WebViewImpl;
+  friend class ReportTimeSwapPromise;
+
+  // WidgetBaseClient overrides:
+  void BeginCommitCompositorFrame() override;
+  void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
+  void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override;
+  void RecordManipulationTypeCounts(cc::ManipulationInfo info) override;
+  void RecordDispatchRafAlignedInputTime(
+      base::TimeTicks raf_aligned_input_start_time) override;
+  void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override;
+  void RecordStartOfFrameMetrics() override;
+  void RecordEndOfFrameMetrics(
+      base::TimeTicks,
+      cc::ActiveFrameSequenceTrackers trackers) override;
+  std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
+      override;
+  std::unique_ptr<cc::WebVitalMetrics> GetWebVitalMetrics() override;
+  void BeginUpdateLayers() override;
+  void EndUpdateLayers() override;
+  void DidCommitAndDrawCompositorFrame() override;
+  std::unique_ptr<cc::LayerTreeFrameSink> AllocateNewLayerTreeFrameSink()
+      override;
+  void DidObserveFirstScrollDelay(
+      base::TimeDelta first_scroll_delay,
+      base::TimeTicks first_scroll_timestamp) override;
+  void DidBeginMainFrame() override;
+  void WillBeginMainFrame() override;
+  void DidCompletePageScaleAnimation() override;
+  void FocusChangeComplete() override;
+  bool WillHandleGestureEvent(const WebGestureEvent& event) override;
+  void WillHandleMouseEvent(const WebMouseEvent& event) override;
+  void ObserveGestureEventAndResult(
+      const WebGestureEvent& gesture_event,
+      const gfx::Vector2dF& unused_delta,
+      const cc::OverscrollBehavior& overscroll_behavior,
+      bool event_processed) override;
+  bool SupportsBufferedTouchEvents() override { return true; }
+  void DidHandleKeyEvent() override;
+  WebTextInputType GetTextInputType() override;
+  void SetCursorVisibilityState(bool is_visible) override;
+  blink::FrameWidget* FrameWidget() override { return this; }
+  void ScheduleAnimation() override;
+  void FocusChanged(bool enable) override;
+  bool ShouldAckSyntheticInputImmediately() override;
+  void UpdateVisualProperties(
+      const VisualProperties& visual_properties) override;
+  void ScheduleAnimationForWebTests() override;
+  bool UpdateScreenRects(const gfx::Rect& widget_screen_rect,
+                         const gfx::Rect& window_screen_rect) override;
+  void OrientationChanged() override;
+  void DidUpdateSurfaceAndScreen(
+      const ScreenInfo& previous_original_screen_info) override;
+  gfx::Rect ViewportVisibleRect() override;
+  const ScreenInfo& GetOriginalScreenInfo() override;
+  base::Optional<blink::mojom::ScreenOrientation> ScreenOrientationOverride()
+      override;
+  void WasHidden() override;
+  void WasShown(bool was_evicted) override;
+  void RunPaintBenchmark(int repeat_count,
+                         cc::PaintBenchmarkResult& result) override;
+  KURL GetURLForDebugTrace() override;
+  float GetTestingDeviceScaleFactorOverride() override;
+
+  // mojom::blink::FrameWidget overrides.
+  void DragTargetDragEnter(const WebDragData&,
+                           const gfx::PointF& point_in_viewport,
+                           const gfx::PointF& screen_point,
+                           DragOperationsMask operations_allowed,
+                           uint32_t key_modifiers,
+                           DragTargetDragEnterCallback callback) override;
+  void DragTargetDragOver(const gfx::PointF& point_in_viewport,
+                          const gfx::PointF& screen_point,
+                          DragOperationsMask operations_allowed,
+                          uint32_t key_modifiers,
+                          DragTargetDragOverCallback callback) override;
+  void DragTargetDragLeave(const gfx::PointF& point_in_viewport,
+                           const gfx::PointF& screen_point) override;
+  void DragTargetDrop(const WebDragData&,
+                      const gfx::PointF& point_in_viewport,
+                      const gfx::PointF& screen_point,
+                      uint32_t key_modifiers) override;
+  void DragSourceSystemDragEnded() override;
+  void SetBackgroundOpaque(bool opaque) override;
+  void SetActive(bool active) override;
+  // For both mainframe and childframe change the text direction of the
+  // currently selected input field (if any).
+  void SetTextDirection(base::i18n::TextDirection direction) override;
+  // Sets the inherited effective touch action on an out-of-process iframe.
+  void SetInheritedEffectiveTouchActionForSubFrame(
+      WebTouchAction touch_action) override;
+  // Toggles render throttling for an out-of-process iframe. Local frames are
+  // throttled based on their visibility in the viewport, but remote frames
+  // have to have throttling information propagated from parent to child
+  // across processes.
+  void UpdateRenderThrottlingStatusForSubFrame(bool is_throttled,
+                                               bool subtree_throttled) override;
+  void EnableDeviceEmulation(const DeviceEmulationParams& parameters) override;
+  void DisableDeviceEmulation() override;
+  // Sets the inert bit on an out-of-process iframe, causing it to ignore
+  // input.
+  void SetIsInertForSubFrame(bool inert) override;
+#if defined(OS_MAC)
+  void GetStringAtPoint(const gfx::Point& point_in_local_root,
+                        GetStringAtPointCallback callback) override;
+#endif
+
+  // PageWidgetEventHandler overrides:
+  WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
+  void HandleMouseDown(LocalFrame&, const WebMouseEvent&) override;
+  void HandleMouseLeave(LocalFrame&, const WebMouseEvent&) override;
+  WebInputEventResult HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
+  WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
+  WebInputEventResult HandleMouseWheel(LocalFrame&,
+                                       const WebMouseWheelEvent&) override;
+  WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
+
+  WebInputEventResult HandleCapturedMouseEvent(const WebCoalescedInputEvent&);
+  void MouseContextMenu(const WebMouseEvent&);
+  void CancelDrag();
+  void RequestAnimationAfterDelayTimerFired(TimerBase*);
+  void PresentationCallbackForMeaningfulLayout(blink::WebSwapResult,
+                                               base::TimeTicks);
+
+  void ForEachRemoteFrameControlledByWidget(
+      const base::RepeatingCallback<void(RemoteFrame*)>& callback);
+
+  void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
+
+  // Finds the parameters required for scrolling the focused editable |element|
+  // into view. |out_rect_to_scroll| is used for recursive scrolling of the
+  // element into view and contains all or part of element's bounding box and
+  // always includes the caret and is with respect to absolute coordinates.
+  mojom::blink::ScrollIntoViewParamsPtr
+  GetScrollParamsForFocusedEditableElement(const Element& element,
+                                           PhysicalRect& out_rect_to_scroll);
+
+  enum DragAction { kDragEnter, kDragOver };
+  // Consolidate some common code between starting a drag over a target and
+  // updating a drag over a target. If we're starting a drag, |isEntering|
+  // should be true.
+  DragOperation DragTargetDragEnterOrOver(const gfx::PointF& point_in_viewport,
+                                          const gfx::PointF& screen_point,
+                                          DragAction,
+                                          uint32_t key_modifiers);
+
+  // Helper function to call VisualViewport::viewportToRootFrame().
+  gfx::PointF ViewportToRootFrame(const gfx::PointF& point_in_viewport) const;
+
+  WebViewImpl* View() const;
+
+  // Returns the page object associated with this widget. This may be null when
+  // the page is shutting down, but will be valid at all other times.
+  Page* GetPage() const;
+
+  mojom::blink::FrameWidgetHost* GetAssociatedFrameWidgetHost() const;
+
+  // Notifies RenderWidgetHostImpl that the frame widget has painted something.
+  void DidMeaningfulLayout(WebMeaningfulLayout layout_type);
+
+  // Enable or disable auto-resize. This is part of
+  // UpdateVisualProperties though tests may call to it more directly.
+  void SetAutoResizeMode(bool auto_resize,
+                         const gfx::Size& min_size_before_dsf,
+                         const gfx::Size& max_size_before_dsf,
+                         float device_scale_factor);
+
+  // Called when a gesture event has been processed.
+  void DidHandleGestureEvent(const WebGestureEvent& event);
+
+  // Called to update if pointerrawupdate events should be sent.
+  void SetHasPointerRawUpdateEventHandlers(bool);
+
+  // Helper function to process events while pointer locked.
+  void PointerLockMouseEvent(const WebCoalescedInputEvent&);
+  bool IsPointerLocked();
+
+  // The fullscreen granted status from the most recent VisualProperties update.
+  bool IsFullscreenGranted();
+
+  void NotifyPageScaleFactorChanged(float page_scale_factor,
+                                    bool is_pinch_gesture_active);
+
+  // Helper for notifying frame-level objects that care about input events.
+  // TODO: With some effort, this could be folded into a common implementation
+  // of WebViewImpl::HandleInputEvent and WebFrameWidgetImpl::HandleInputEvent.
+  void NotifyInputObservers(const WebCoalescedInputEvent& coalesced_event);
+
+  Frame* FocusedCoreFrame() const;
+
+  // Returns the currently focused `Element` in any `LocalFrame` owned by the
+  // associated `WebView`.
+  Element* FocusedElement() const;
+
+  // Perform a hit test for a point relative to the root frame of the page.
+  HitTestResult HitTestResultForRootFramePos(
+      const FloatPoint& pos_in_root_frame);
+
+  // Called during |UpdateVisualProperties| to apply the new size to the widget.
+  void ApplyVisualPropertiesSizing(const VisualProperties& visual_properties);
+
+  // Returns the current state of synchronous resize mode for testing.
+  bool SynchronousResizeModeForTestingEnabled();
+
+  // A copy of the web drop data object we received from the browser.
+  Member<DataObject> current_drag_data_;
+
+  bool doing_drag_and_drop_ = false;
+
+  // The available drag operations (copy, move link...) allowed by the source.
+  DragOperation operations_allowed_ = kDragOperationNone;
+
+  // The current drag operation as negotiated by the source and destination.
+  // When not equal to DragOperationNone, the drag data can be dropped onto the
+  // current drop target in this WebView (the drop target can accept the drop).
+  DragOperation drag_operation_ = kDragOperationNone;
+
+  // This field stores drag/drop related info for the event that is currently
+  // being handled. If the current event results in starting a drag/drop
+  // session, this info is sent to the browser along with other drag/drop info.
+  mojom::blink::DragEventSourceInfo possible_drag_event_info_;
+
+  // Base functionality all widgets have. This is a member as to avoid
+  // complicated inheritance structures.
+  std::unique_ptr<WidgetBase> widget_base_;
+
+  // The last seen page scale state, which comes from the main frame if we're
+  // in a child frame. This state is propagated through the RenderWidget tree
+  // passed to any new child RenderWidget.
+  float page_scale_factor_in_mainframe_ = 1.f;
+  bool is_pinch_gesture_active_in_mainframe_ = false;
+
+  // If set, the (plugin) element which has mouse capture.
+  // TODO(dtapuska): Move to private once all input handling is moved to
+  // base class.
+  Member<HTMLPlugInElement> mouse_capture_element_;
+
+  // The size of the widget in viewport coordinates. This is slightly different
+  // than the WebViewImpl::size_ since isn't set in auto resize mode.
+  base::Optional<gfx::Size> size_;
+
+  static bool ignore_input_events_;
+
+  WebWidgetClient* client_;
+
+  const viz::FrameSinkId frame_sink_id_;
+
+  // WebFrameWidget is associated with a subtree of the frame tree,
+  // corresponding to a maximal connected tree of LocalFrames. This member
+  // points to the root of that subtree.
+  Member<WebLocalFrameImpl> local_root_;
+
+  mojom::blink::DisplayMode display_mode_;
+
+  WebVector<gfx::Rect> window_segments_;
+
+  // This is owned by the LayerTreeHostImpl, and should only be used on the
+  // compositor thread, so we keep the TaskRunner where you post tasks to
+  // make that happen.
+  base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> mutator_dispatcher_;
+  scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner_;
+
+  // The |paint_dispatcher_| should only be dereferenced on the
+  // |paint_task_runner_| (in practice this is the compositor thread). We keep a
+  // copy of it here to provide to new PaintWorkletProxyClient objects (which
+  // run on the worklet thread) so that they can talk to the
+  // PaintWorkletPaintDispatcher on the compositor thread.
+  base::WeakPtr<PaintWorkletPaintDispatcher> paint_dispatcher_;
+  scoped_refptr<base::SingleThreadTaskRunner> paint_task_runner_;
+
+  std::unique_ptr<TaskRunnerTimer<WebFrameWidgetImpl>>
+      request_animation_after_delay_timer_;
+
+  // WebFrameWidgetImpl is not tied to ExecutionContext
+  HeapMojoAssociatedRemote<mojom::blink::FrameWidgetHost,
+                           HeapMojoWrapperMode::kWithoutContextObserver>
+      frame_widget_host_{nullptr};
+  // WebFrameWidgetImpl is not tied to ExecutionContext
+  HeapMojoAssociatedReceiver<mojom::blink::FrameWidget,
+                             WebFrameWidgetImpl,
+                             HeapMojoWrapperMode::kWithoutContextObserver>
+      receiver_{this, nullptr};
+  HeapMojoReceiver<viz::mojom::blink::InputTargetClient,
+                   WebFrameWidgetImpl,
+                   HeapMojoWrapperMode::kWithoutContextObserver>
+      input_target_receiver_{this, nullptr};
+
+  // Different consumers in the browser process makes different assumptions, so
+  // must always send the first IPC regardless of value.
+  base::Optional<bool> has_touch_handlers_;
+
+  Vector<mojom::blink::EditCommandPtr> edit_commands_;
+
+  base::Optional<gfx::Point> host_context_menu_location_;
+  uint32_t last_capture_sequence_number_ = 0u;
+
+  // Indicates whether tab-initiated fullscreen was granted.
+  bool is_fullscreen_granted_ = false;
+
+  // Indicates whether we need to consume scroll gestures to move cursor.
+  bool swipe_to_move_cursor_activated_ = false;
+
+  // Set when a measurement begins, reset when the measurement is taken.
+  base::Optional<base::TimeTicks> update_layers_start_time_;
+
+  // Metrics for gathering time for commit of compositor frame.
+  base::Optional<base::TimeTicks> commit_compositor_frame_start_time_;
+
+  // Present when emulation is enabled, only on a main frame's WebFrameWidget.
+  // Used to override values given from the browser such as ScreenInfo,
+  // WidgetScreenRect, WindowScreenRect, and the widget's size.
+  Member<ScreenMetricsEmulator> device_emulator_;
+
+  // keyPress events to be suppressed if the associated keyDown event was
+  // handled.
+  bool suppress_next_keypress_event_ = false;
+
+  // This struct contains data that is only valid for child local root widgets.
+  // You should use `child_data()` to access it.
+  struct ChildLocalRootData {
+    gfx::Rect compositor_visible_rect;
+    bool did_suspend_parsing = false;
+  } child_local_root_data_;
+
+  ChildLocalRootData& child_data() {
+    DCHECK(ForSubframe());
+    return child_local_root_data_;
+  }
+
+  // Web tests override the zoom factor in the renderer with this. We store it
+  // to keep the override if the browser passes along VisualProperties with the
+  // real device scale factor. A value of -INFINITY means this is ignored.
+  // It is always valid to read this variable but it can only be set for main
+  // frame widgets.
+  double zoom_level_for_testing_ = -INFINITY;
+
+  // Web tests override the device scale factor in the renderer with this. We
+  // store it to keep the override if the browser passes along VisualProperties
+  // with the real device scale factor. A value of 0.f means this is ignored.
+  // It is always valid to read this variable but it can only be set for main
+  // frame widgets.
+  float device_scale_factor_for_testing_ = 0;
+
+  // This struct contains data that is only valid for main frame widgets.
+  // You should use `main_data()` to access it.
+  struct MainFrameData {
+    // `UpdateLifecycle()` generates `WebMeaningfulLayout` events these
+    // variables track what events should be generated. They are only applicable
+    // for main frame widgets.
+    bool should_dispatch_first_visually_non_empty_layout = false;
+    bool should_dispatch_first_layout_after_finished_parsing = false;
+    bool should_dispatch_first_layout_after_finished_loading = false;
+    // Last background color sent to the browser. Only set for main frames.
+    base::Optional<SkColor> last_background_color;
+    // This bit is used to tell if this is a nested widget (an "inner web
+    // contents") like a <webview> or <portal> widget. If false, the widget is
+    // the top level widget.
+    bool is_for_nested_main_frame = false;
+
+    // In web tests, synchronous resizing mode may be used. Normally each
+    // widget's size is controlled by IPC from the browser. In synchronous
+    // resize mode the renderer controls the size directly, and IPCs from the
+    // browser must be ignored. This was deprecated but then later undeprecated,
+    // so it is now called unfortunate instead. See https://crbug.com/309760.
+    // When this is enabled the various size properties will be controlled
+    // directly when SetWindowRect() is called instead of needing a round trip
+    // through the browser. Note that SetWindowRectSynchronouslyForTesting()
+    // provides a secondary way to control the size of the FrameWidget
+    // independently from the renderer process, without the use of this mode,
+    // however it would be overridden by the browser if they disagree.
+    bool synchronous_resize_mode_for_testing = false;
+
+  } main_frame_data_;
+
+  MainFrameData& main_data() {
+    DCHECK(ForMainFrame());
+    return main_frame_data_;
+  }
+
+  const MainFrameData& main_data() const {
+    DCHECK(ForMainFrame());
+    return main_frame_data_;
+  }
+
+  // Whether this widget is for a child local root, or otherwise a main frame.
+  const bool is_for_child_local_root_;
+
+  // This stores the last hidden page popup. If a GestureTap attempts to open
+  // the popup that is closed by its previous GestureTapDown, the popup remains
+  // closed.
+  scoped_refptr<WebPagePopupImpl> last_hidden_page_popup_;
+
+  SelfKeepAlive<WebFrameWidgetImpl> self_keep_alive_;
 };
 
+// Convenience type for creation method taken by
+// InstallCreateMainFrameWebFrameWidgetHook(). The method signature matches the
+// WebFrameWidgetImpl constructor.
+using CreateMainFrameWebFrameWidgetFunction =
+    WebFrameWidgetImpl* (*)(base::PassKey<WebFrameWidget>,
+                            WebWidgetClient&,
+                            CrossVariantMojoAssociatedRemote<
+                                mojom::blink::FrameWidgetHostInterfaceBase>
+                                frame_widget_host,
+                            CrossVariantMojoAssociatedReceiver<
+                                mojom::blink::FrameWidgetInterfaceBase>
+                                frame_widget,
+                            CrossVariantMojoAssociatedRemote<
+                                mojom::blink::WidgetHostInterfaceBase>
+                                widget_host,
+                            CrossVariantMojoAssociatedReceiver<
+                                mojom::blink::WidgetInterfaceBase> widget,
+                            scoped_refptr<base::SingleThreadTaskRunner>
+                                task_runner,
+                            const viz::FrameSinkId& frame_sink_id,
+                            bool hidden,
+                            bool never_composited,
+                            bool is_for_child_local_root,
+                            bool is_for_nested_main_frame);
+// Overrides the implementation of WebFrameWidget::CreateForMainFrame() function
+// below. Used by tests to override some functionality on WebFrameWidgetImpl.
+void CORE_EXPORT InstallCreateMainFrameWebFrameWidgetHook(
+    CreateMainFrameWebFrameWidgetFunction create_widget);
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
index 2b9fcb4..7b5e664 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -14,7 +14,7 @@
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
 
@@ -52,7 +52,7 @@
 class WebFrameWidgetSimTest : public SimTest {};
 
 // Tests that if a WebView is auto-resized, the associated
-// WebViewFrameWidget requests a new viz::LocalSurfaceId to be allocated on the
+// WebFrameWidgetImpl requests a new viz::LocalSurfaceId to be allocated on the
 // impl thread.
 TEST_F(WebFrameWidgetSimTest, AutoResizeAllocatedLocalSurfaceId) {
   viz::ParentLocalSurfaceIdAllocator allocator;
@@ -78,8 +78,7 @@
                    ->new_local_surface_id_request_for_testing());
 
   constexpr gfx::Size size(200, 200);
-  static_cast<WebViewFrameWidget*>(WebView().MainFrameViewWidget())
-      ->DidAutoResize(size);
+  WebView().MainFrameViewWidget()->DidAutoResize(size);
   EXPECT_EQ(allocator.GetCurrentLocalSurfaceId(),
             WebView().MainFrameViewWidget()->LocalSurfaceIdFromParent());
   EXPECT_TRUE(WebView()
@@ -139,14 +138,13 @@
 }
 #endif  // defined(OS_ANDROID)
 
-// A test that forces a RemoteMainFrame to be created and the LocalFrameRoot
-// to be a WebFrameWidgetImpl.
-class WebFrameWidgetImplSimTest : public SimTest {
+// A test that forces a RemoteMainFrame to be created.
+class WebFrameWidgetImplRemoteFrameSimTest : public SimTest {
  public:
   void SetUp() override {
     SimTest::SetUp();
     InitializeRemote();
-    CHECK(static_cast<WebFrameWidgetBase*>(LocalFrameRoot().FrameWidget())
+    CHECK(static_cast<WebFrameWidgetImpl*>(LocalFrameRoot().FrameWidget())
               ->ForSubframe());
   }
 
@@ -158,7 +156,7 @@
 // Tests that the value of VisualProperties::is_pinch_gesture_active is
 // propagated to the LayerTreeHost when properties are synced for child local
 // roots.
-TEST_F(WebFrameWidgetImplSimTest,
+TEST_F(WebFrameWidgetImplRemoteFrameSimTest,
        ActivePinchGestureUpdatesLayerTreeHostSubFrame) {
   cc::LayerTreeHost* layer_tree_host = LocalFrameRootWidget()->LayerTreeHost();
   EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing());
@@ -223,11 +221,11 @@
   DISALLOW_COPY_AND_ASSIGN(MockHandledEventCallback);
 };
 
-class MockWebViewFrameWidget : public WebViewFrameWidget {
+class MockWebFrameWidgetImpl : public WebFrameWidgetImpl {
  public:
   template <typename... Args>
-  explicit MockWebViewFrameWidget(Args&&... args)
-      : WebViewFrameWidget(std::forward<Args>(args)...) {}
+  explicit MockWebFrameWidgetImpl(Args&&... args)
+      : WebFrameWidgetImpl(std::forward<Args>(args)...) {}
 
   MOCK_METHOD1(HandleInputEvent,
                WebInputEventResult(const WebCoalescedInputEvent&));
@@ -242,10 +240,9 @@
   MOCK_METHOD1(WillHandleGestureEvent, bool(const WebGestureEvent& event));
 };
 
-WebViewFrameWidget* CreateWebViewFrameWidget(
+WebFrameWidgetImpl* CreateMainFrameWebFrameWidget(
     base::PassKey<WebFrameWidget> pass_key,
     WebWidgetClient& client,
-    WebViewImpl& web_view_impl,
     CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>
         frame_widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>
@@ -255,25 +252,26 @@
     CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     const viz::FrameSinkId& frame_sink_id,
-    bool is_for_nested_main_frame,
     bool hidden,
-    bool never_composited) {
-  return MakeGarbageCollected<MockWebViewFrameWidget>(
-      pass_key, client, web_view_impl, std::move(frame_widget_host),
-      std::move(frame_widget), std::move(widget_host), std::move(widget),
-      std::move(task_runner), frame_sink_id, is_for_nested_main_frame, hidden,
-      never_composited);
+    bool never_composited,
+    bool is_for_child_local_root,
+    bool is_for_nested_main_frame) {
+  return MakeGarbageCollected<MockWebFrameWidgetImpl>(
+      pass_key, client, std::move(frame_widget_host), std::move(frame_widget),
+      std::move(widget_host), std::move(widget), std::move(task_runner),
+      frame_sink_id, hidden, never_composited, is_for_child_local_root,
+      is_for_nested_main_frame);
 }
 
-class WebViewFrameWidgetSimTest : public SimTest {
+class WebFrameWidgetImplSimTest : public SimTest {
  public:
   void SetUp() override {
-    InstallCreateWebViewFrameWidgetHook(CreateWebViewFrameWidget);
+    InstallCreateMainFrameWebFrameWidgetHook(CreateMainFrameWebFrameWidget);
     SimTest::SetUp();
   }
 
-  MockWebViewFrameWidget* MockMainFrameWidget() {
-    return static_cast<MockWebViewFrameWidget*>(MainFrame().FrameWidget());
+  MockWebFrameWidgetImpl* MockMainFrameWidget() {
+    return static_cast<MockWebFrameWidgetImpl*>(MainFrame().FrameWidget());
   }
 
   void SendInputEvent(const WebInputEvent& event,
@@ -305,7 +303,7 @@
   base::HistogramTester histogram_tester_;
 };
 
-TEST_F(WebViewFrameWidgetSimTest, CursorChange) {
+TEST_F(WebFrameWidgetImplSimTest, CursorChange) {
   ui::Cursor cursor;
 
   MockMainFrameWidget()->SetCursor(cursor);
@@ -329,10 +327,10 @@
   EXPECT_EQ(WebWidgetClient().CursorSetCount(), 2u);
 }
 
-TEST_F(WebViewFrameWidgetSimTest, EventOverscroll) {
+TEST_F(WebFrameWidgetImplSimTest, EventOverscroll) {
   ON_CALL(*MockMainFrameWidget(), WillHandleGestureEvent(_))
       .WillByDefault(testing::Invoke(
-          this, &WebViewFrameWidgetSimTest::OverscrollGestureEvent));
+          this, &WebFrameWidgetImplSimTest::OverscrollGestureEvent));
   EXPECT_CALL(*MockMainFrameWidget(), HandleInputEvent(_))
       .WillRepeatedly(::testing::Return(WebInputEventResult::kNotHandled));
 
@@ -356,7 +354,7 @@
   SendInputEvent(scroll, handled_event.GetCallback());
 }
 
-TEST_F(WebViewFrameWidgetSimTest, RenderWidgetInputEventUmaMetrics) {
+TEST_F(WebFrameWidgetImplSimTest, RenderWidgetInputEventUmaMetrics) {
   SyntheticWebTouchEvent touch;
   touch.PressPoint(10, 10);
   touch.touch_start_or_first_touch_move = true;
@@ -421,7 +419,7 @@
 
 // Ensures that the compositor thread gets sent the gesture event & overscroll
 // amount for an overscroll initiated by a touchpad.
-TEST_F(WebViewFrameWidgetSimTest, SendElasticOverscrollForTouchpad) {
+TEST_F(WebFrameWidgetImplSimTest, SendElasticOverscrollForTouchpad) {
   WebGestureEvent scroll(WebInputEvent::Type::kGestureScrollUpdate,
                          WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                          WebGestureDevice::kTouchpad);
@@ -441,7 +439,7 @@
 
 // Ensures that the compositor thread gets sent the gesture event & overscroll
 // amount for an overscroll initiated by a touchscreen.
-TEST_F(WebViewFrameWidgetSimTest, SendElasticOverscrollForTouchscreen) {
+TEST_F(WebFrameWidgetImplSimTest, SendElasticOverscrollForTouchscreen) {
   WebGestureEvent scroll(WebInputEvent::Type::kGestureScrollUpdate,
                          WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                          WebGestureDevice::kTouchscreen);
@@ -478,8 +476,8 @@
     color_layer->SetBackgroundColor(SK_ColorRED);
   }
 
-  WebViewFrameWidget* FrameWidgetBase() {
-    return static_cast<WebViewFrameWidget*>(MainFrame().FrameWidget());
+  WebFrameWidgetImpl* FrameWidgetBase() {
+    return static_cast<WebFrameWidgetImpl*>(MainFrame().FrameWidget());
   }
 
   // |swap_to_presentation| determines how long after swap should presentation
@@ -615,13 +613,13 @@
 
   // Expect listener does not get called, due to devtools flag.
   touch.MovePoint(0, 12, 12);
-  WebFrameWidgetBase::SetIgnoreInputEvents(true);
+  WebFrameWidgetImpl::SetIgnoreInputEvents(true);
   widget->ProcessInputEventSynchronouslyForTesting(
       WebCoalescedInputEvent(touch.Clone(), {}, {}, ui::LatencyInfo()),
       base::DoNothing());
-  EXPECT_TRUE(WebFrameWidgetBase::IgnoreInputEvents());
+  EXPECT_TRUE(WebFrameWidgetImpl::IgnoreInputEvents());
   EXPECT_FALSE(listener->GetInvokedStateAndReset());
-  WebFrameWidgetBase::SetIgnoreInputEvents(false);
+  WebFrameWidgetImpl::SetIgnoreInputEvents(false);
 
   // Expect listener does not get called, due to drag.
   touch.MovePoint(0, 14, 14);
@@ -631,7 +629,7 @@
       WebCoalescedInputEvent(touch.Clone(), {}, {}, ui::LatencyInfo()),
       base::DoNothing());
   EXPECT_TRUE(widget->DoingDragAndDrop());
-  EXPECT_FALSE(WebFrameWidgetBase::IgnoreInputEvents());
+  EXPECT_FALSE(WebFrameWidgetImpl::IgnoreInputEvents());
   EXPECT_FALSE(listener->GetInvokedStateAndReset());
 }
 
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 06be9856..9d46d66d 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -191,7 +191,7 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/smart_clip.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
 #include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
@@ -2431,7 +2431,7 @@
   }
 }
 
-void WebLocalFrameImpl::SetFrameWidget(WebFrameWidgetBase* frame_widget) {
+void WebLocalFrameImpl::SetFrameWidget(WebFrameWidgetImpl* frame_widget) {
   frame_widget_ = frame_widget;
 }
 
@@ -2601,7 +2601,7 @@
   spell_check_panel_host_client_ = spell_check_panel_host_client;
 }
 
-WebFrameWidgetBase* WebLocalFrameImpl::LocalRootFrameWidget() {
+WebFrameWidgetImpl* WebLocalFrameImpl::LocalRootFrameWidget() {
   CHECK(LocalRoot());
   return LocalRoot()->FrameWidgetImpl();
 }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 8c155a11..b276be0 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -77,7 +77,7 @@
 class WebContentSettingsClient;
 class WebDevToolsAgentImpl;
 class WebLocalFrameClient;
-class WebFrameWidgetBase;
+class WebFrameWidgetImpl;
 class WebNode;
 class WebPerformance;
 class WebRemoteFrameImpl;
@@ -444,7 +444,7 @@
 
   void SetClient(WebLocalFrameClient* client) { client_ = client; }
 
-  WebFrameWidgetBase* FrameWidgetImpl() { return frame_widget_; }
+  WebFrameWidgetImpl* FrameWidgetImpl() { return frame_widget_; }
 
   WebContentSettingsClient* GetContentSettingsClient() {
     return content_settings_client_;
@@ -461,11 +461,11 @@
   // Otherwise creates it and then returns.
   TextFinder& EnsureTextFinder();
 
-  void SetFrameWidget(WebFrameWidgetBase*);
+  void SetFrameWidget(WebFrameWidgetImpl*);
 
   // TODO(dcheng): Remove this and make |FrameWidget()| always return something
   // useful.
-  WebFrameWidgetBase* LocalRootFrameWidget();
+  WebFrameWidgetImpl* LocalRootFrameWidget();
 
   // Returns true if the frame is focused.
   bool IsFocused() const;
@@ -538,7 +538,7 @@
 
   // This is set if the frame is the root of a local frame tree, and requires a
   // widget for layout.
-  Member<WebFrameWidgetBase> frame_widget_;
+  Member<WebFrameWidgetImpl> frame_widget_;
 
   Member<WebDevToolsAgentImpl> dev_tools_agent_;
 
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
deleted file mode 100644
index 7e28552..0000000
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
-
-#include "base/debug/crash_logging.h"
-#include "build/build_config.h"
-#include "third_party/blink/public/common/input/web_keyboard_event.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_autofill_client.h"
-#include "third_party/blink/public/web/web_view_client.h"
-#include "third_party/blink/renderer/core/editing/frame_selection.h"
-#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
-#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
-#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
-#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
-#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
-#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
-#include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/html/html_plugin_element.h"
-#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
-#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/loader/interactive_detector.h"
-#include "third_party/blink/renderer/core/page/context_menu_controller.h"
-#include "third_party/blink/renderer/core/page/focus_controller.h"
-#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/widget/widget_base.h"
-
-namespace blink {
-
-WebViewFrameWidget::WebViewFrameWidget(
-    base::PassKey<WebFrameWidget>,
-    WebWidgetClient& client,
-    WebViewImpl& web_view,
-    CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
-        frame_widget_host,
-    CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
-        frame_widget,
-    CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
-        widget_host,
-    CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
-        widget,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    const viz::FrameSinkId& frame_sink_id,
-    bool is_for_nested_main_frame,
-    bool hidden,
-    bool never_composited)
-    : WebFrameWidgetBase(client,
-                         std::move(frame_widget_host),
-                         std::move(frame_widget),
-                         std::move(widget_host),
-                         std::move(widget),
-                         task_runner,
-                         frame_sink_id,
-                         hidden,
-                         never_composited,
-                         /*is_for_child_local_root=*/false,
-                         is_for_nested_main_frame) {
-  web_view.SetMainFrameViewWidget(this);
-}
-
-WebViewFrameWidget::~WebViewFrameWidget() = default;
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
deleted file mode 100644
index 73bd6b5..0000000
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_VIEW_FRAME_WIDGET_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_VIEW_FRAME_WIDGET_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/single_thread_task_runner.h"
-#include "base/types/pass_key.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/platform/graphics/apply_viewport_changes.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
-
-namespace blink {
-
-class WebFrameWidget;
-class WebViewImpl;
-class WebWidgetClient;
-
-// Shim class to help normalize the widget interfaces in the Blink public API.
-// For OOPI, subframes have WebFrameWidgets for input and rendering.
-// Unfortunately, the main frame still uses WebView's WebWidget for input and
-// rendering. This results in complex code, since there are two different
-// implementations of WebWidget and code needs to have branches to handle both
-// cases.
-// This class allows a Blink embedder to create a WebFrameWidget that can be
-// used for the main frame. Internally, it currently wraps WebView's WebWidget
-// and just forwards almost everything to it.
-// After the embedder starts using a WebFrameWidget for the main frame,
-// WebView will be updated to no longer inherit WebWidget. The eventual goal is
-// to unfork the widget code duplicated in WebFrameWidgetImpl and WebViewImpl
-// into one class.
-// A more detailed writeup of this transition can be read at
-// https://goo.gl/7yVrnb.
-class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
- public:
-  WebViewFrameWidget(
-      base::PassKey<WebFrameWidget>,
-      WebWidgetClient&,
-      WebViewImpl&,
-      CrossVariantMojoAssociatedRemote<
-          mojom::blink::FrameWidgetHostInterfaceBase> frame_widget_host,
-      CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
-          frame_widget,
-      CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
-          widget_host,
-      CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
-          widget,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      const viz::FrameSinkId& frame_sink_id,
-      bool is_for_nested_main_frame,
-      bool hidden,
-      bool never_composited);
-  ~WebViewFrameWidget() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebViewFrameWidget);
-};
-
-// Convenience type for creation method taken by
-// InstallCreateWebViewFrameWidgetHook(). The method signature matches the
-// WebViewFrameWidget constructor.
-using CreateWebViewFrameWidgetFunction =
-    WebViewFrameWidget* (*)(base::PassKey<WebFrameWidget>,
-                            WebWidgetClient&,
-                            WebViewImpl&,
-                            CrossVariantMojoAssociatedRemote<
-                                mojom::blink::FrameWidgetHostInterfaceBase>
-                                frame_widget_host,
-                            CrossVariantMojoAssociatedReceiver<
-                                mojom::blink::FrameWidgetInterfaceBase>
-                                frame_widget,
-                            CrossVariantMojoAssociatedRemote<
-                                mojom::blink::WidgetHostInterfaceBase>
-                                widget_host,
-                            CrossVariantMojoAssociatedReceiver<
-                                mojom::blink::WidgetInterfaceBase> widget,
-                            scoped_refptr<base::SingleThreadTaskRunner>
-                                task_runner,
-                            const viz::FrameSinkId& frame_sink_id,
-                            bool is_for_nested_main_frame,
-                            bool hidden,
-                            bool never_composited);
-// Overrides the implementation of WebFrameWidget::CreateForMainFrame() function
-// below. Used by tests to override some functionality on WebViewFrameWidget.
-void CORE_EXPORT InstallCreateWebViewFrameWidgetHook(
-    CreateWebViewFrameWidgetFunction create_widget);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_VIEW_FRAME_WIDGET_H_
diff --git a/third_party/blink/renderer/core/html/forms/external_popup_menu.cc b/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
index 99a12ecb..841bfb95 100644
--- a/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
+++ b/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
@@ -40,7 +40,7 @@
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/forms/html_option_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_select_element.h"
diff --git a/third_party/blink/renderer/core/html/html_meta_element_test.cc b/third_party/blink/renderer/core/html/html_meta_element_test.cc
index f2ac9d6..ef591be 100644
--- a/third_party/blink/renderer/core/html/html_meta_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/viewport_data.h"
 #include "third_party/blink/renderer/core/html/html_head_element.h"
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc
index 1d0175c..ee9b95ce 100644
--- a/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -29,7 +29,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc
index 9e97ed5..8fb4fb4 100644
--- a/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -33,8 +33,8 @@
 #include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
 #include "third_party/blink/renderer/core/scroll/scroll_customization.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/widget/input/input_metrics.h"
 
 namespace blink {
 namespace {
@@ -422,23 +422,23 @@
   if (non_composited_main_thread_scrolling_reasons) {
     DCHECK(cc::MainThreadScrollingReason::HasNonCompositedScrollReasons(
         non_composited_main_thread_scrolling_reasons));
-    uint32_t main_thread_scrolling_reason_enum_max =
-        cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount + 1;
+    // The enum in cc::MainThreadScrollingReason simultaneously defines actual
+    // bitmask values and indices into the bitmask, making this loop a bit
+    // confusing.
+    //
+    // This stems from the fact that kNotScrollingOnMain is recorded in the
+    // histograms as value 0. However, the 0th bit is not actually reserved and
+    // has a separate, well-defined meaning. kNotScrollingOnMain is only
+    // recorded when *no* bits are set.
+    //
+    // As such, when recording any reason that's not kNotScrollingOnMain (i.e.
+    // recording the index of a set bit), the index must be incremented by 1 to
+    // be recorded properly.
     for (uint32_t i = cc::MainThreadScrollingReason::kNonCompositedReasonsFirst;
          i <= cc::MainThreadScrollingReason::kNonCompositedReasonsLast; ++i) {
       unsigned val = 1 << i;
       if (non_composited_main_thread_scrolling_reasons & val) {
-        if (device == WebGestureDevice::kTouchscreen) {
-          DEFINE_STATIC_LOCAL(EnumerationHistogram, touch_histogram,
-                              ("Renderer4.MainThreadGestureScrollReason",
-                               main_thread_scrolling_reason_enum_max));
-          touch_histogram.Count(i + 1);
-        } else {
-          DEFINE_STATIC_LOCAL(EnumerationHistogram, wheel_histogram,
-                              ("Renderer4.MainThreadWheelScrollReason",
-                               main_thread_scrolling_reason_enum_max));
-          wheel_histogram.Count(i + 1);
-        }
+        RecordScrollReasonMetric(device, i + 1);
       }
     }
   }
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index c1769174..4d15d05 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -56,7 +56,7 @@
 #include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
@@ -476,7 +476,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
@@ -498,7 +498,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
@@ -517,7 +517,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
@@ -538,7 +538,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
@@ -560,7 +560,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
@@ -583,7 +583,7 @@
       return response;
   }
   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
-  WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
+  WebFrameWidgetImpl* widget_impl = static_cast<WebFrameWidgetImpl*>(widget);
   // While a frame is being detached the inspector will shutdown and
   // turn off debug overlays, but the WebFrameWidget is already gone.
   if (widget_impl) {
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index 2dbc8d2..03a61c10 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -178,8 +178,8 @@
     return PositionWithAffinity();
   if (inner_possibly_pseudo_node_->IsPseudoElement() &&
       inner_possibly_pseudo_node_->GetPseudoId() == kPseudoIdBefore) {
-    return PositionWithAffinity(MostForwardCaretPosition(
-        Position(inner_node_, PositionAnchorType::kBeforeChildren)));
+    return PositionWithAffinity(
+        MostForwardCaretPosition(Position::FirstPositionInNode(*inner_node_)));
   }
   if (box_fragment_ &&
       RuntimeEnabledFeatures::LayoutNGFullPositionForPointEnabled())
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index 165089ac..42c8e432 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -154,6 +154,9 @@
   if (!is_active_)
     return false;
 
+  if (object.GetDocument().IsPrintingOrPaintingPreview())
+    return false;
+
   // SVG elements don't participate in the normal layout algorithms and are
   // more likely to be used for animations.
   if (object.IsSVGChild())
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
index 759763f..4ce7967c 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
 
 #include "third_party/blink/public/common/input/web_mouse_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
@@ -390,4 +391,83 @@
   EXPECT_FLOAT_EQ(0.09 * (490.0 / 800.0), GetLayoutShiftTracker().Score());
 }
 
+TEST_F(LayoutShiftTrackerTest, ContentVisibilityAutoFirstPaint) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+        content-visibility: auto;
+        contain-intrinsic-size: 1px;
+        width: 100px;
+      }
+    </style>
+    <div id=target>
+      <div style="width: 100px; height: 100px"></div>
+    </div>
+  )HTML");
+  auto* target = To<LayoutBox>(GetLayoutObjectByElementId("target"));
+
+  // Because it's on-screen on the first frame, #target renders at size
+  // 100x100 on the first frame, via a synchronous second layout, and there is
+  // no CLS impact.
+  EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
+  EXPECT_EQ(LayoutSize(100, 100), target->Size());
+}
+
+TEST_F(LayoutShiftTrackerTest,
+       ContentVisibilityAutoOffscreenAfterScrollFirstPaint) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+        content-visibility: auto;
+        contain-intrinsic-size: 1px;
+        width: 100px;
+      }
+    </style>
+    <div id=target style="position: relative; top: 100000px">
+      <div style="width: 100px; height: 100px"></div>
+    </div>
+  )HTML");
+  auto* target = To<LayoutBox>(GetLayoutObjectByElementId("target"));
+
+  // #target starts offsceen, which doesn't count for CLS.
+  EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
+  EXPECT_EQ(LayoutSize(100, 1), target->Size());
+
+  // In the next frame, we scroll it onto the screen, but it still doesn't
+  // count for CLS, and its subtree is not yet unskipped because the
+  // intersection observation takes effect on the subsequent frame.
+  GetDocument().domWindow()->scrollTo(0, 100000);
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
+  EXPECT_EQ(LayoutSize(100, 1), target->Size());
+
+  // Now the subtree is unskipped, and #target renders at size 100x100.
+  // Nevertheless, there is no impact on CLS.
+  UpdateAllLifecyclePhasesForTest();
+  // Target's LayoutObject gets re-attached.
+  target = To<LayoutBox>(GetLayoutObjectByElementId("target"));
+  EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
+  EXPECT_EQ(LayoutSize(100, 100), target->Size());
+}
+
+TEST_F(LayoutShiftTrackerTest, ContentVisibilityHiddenFirstPaint) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+        content-visibility: hidden;
+        contain-intrinsic-size: 1px;
+        width: 100px;
+      }
+    </style>
+    <div id=target>
+      <div style="width: 100px; height: 100px"></div>
+    </div>
+  )HTML");
+  auto* target = To<LayoutBox>(GetLayoutObjectByElementId("target"));
+
+  // Skipped subtrees don't cause CLS impact.
+  EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
+  EXPECT_EQ(LayoutSize(100, 1), target->Size());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
index 7a8aa7c..2058d3c3d 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
@@ -26,7 +26,7 @@
 }
 
 MinMaxSizesResult NGCustomLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   if (!Node().IsCustomLayoutLoaded())
     return FallbackMinMaxSizes(input);
 
diff --git a/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
index 6c6775cf..950ce9da 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
@@ -20,7 +20,7 @@
  public:
   NGCustomLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
   scoped_refptr<const NGLayoutResult> Layout() override;
 
  private:
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 86f112e..3e13652 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -1453,7 +1453,7 @@
 }
 
 MinMaxSizesResult NGFlexLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& child_input) {
+    const MinMaxSizesInput& child_input) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
index f940c17d..b572d9d 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -23,7 +23,7 @@
  public:
   NGFlexLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
   scoped_refptr<const NGLayoutResult> Layout() override;
 
  private:
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 711e36b..b4abd38 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -104,7 +104,7 @@
 }
 
 MinMaxSizesResult NGGridLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   return {MinMaxSizes(), /* depends_on_percentage_block_size */ true};
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
index 0189362..144a396 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -74,7 +74,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
   const NGGridLayoutAlgorithmTrackCollection& ColumnTrackCollection() const;
   const NGGridLayoutAlgorithmTrackCollection& RowTrackCollection() const;
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 33cb185..24cd2072 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
@@ -52,7 +52,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override {
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override {
     NOTREACHED();
     return {MinMaxSizes(), true};
   }
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
index 12e25f2..fb8c3661 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
@@ -269,7 +269,7 @@
 }
 
 MinMaxSizesResult NGMathFractionLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& child_input) {
+    const MinMaxSizesInput& child_input) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
index 43330598..05b8761 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
@@ -19,7 +19,7 @@
  private:
   scoped_refptr<const NGLayoutResult> Layout() final;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 
   void GatherChildren(NGBlockNode* numerator, NGBlockNode* denominator);
 };
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
index 91e05ecce..e757ce0 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.cc
@@ -91,7 +91,7 @@
 }
 
 MinMaxSizesResult NGMathOperatorLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   // TODO(http://crbug.com/1124301) Implement stretchy operators.
 
   MinMaxSizes sizes;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.h
index 3724e848..906a4e9 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_operator_layout_algorithm.h
@@ -21,7 +21,7 @@
 
  private:
   scoped_refptr<const NGLayoutResult> Layout() final;
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
   UChar32 GetBaseCodePoint() const;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
index 227836a..5a2a022 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
@@ -115,7 +115,7 @@
 }
 
 MinMaxSizesResult NGMathPaddedLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
index 809a921..845b691 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
@@ -18,7 +18,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() final;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 
  private:
   LayoutUnit RequestedLSpace() const;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
index 2df1cba..8872d76f 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
@@ -194,7 +194,7 @@
 }
 
 MinMaxSizesResult NGMathRadicalLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   DCHECK(IsValidMathMLRadical(Node()));
 
   NGBlockNode base = nullptr;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.h
index 5b0557b..fcc955b 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.h
@@ -19,7 +19,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() final;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 
  private:
   bool HasIndex() const;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
index bf7385e8..7b2427d 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
@@ -154,7 +154,7 @@
 }
 
 MinMaxSizesResult NGMathRowLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& child_input) {
+    const MinMaxSizesInput& child_input) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
index a097032..478fc816 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
@@ -42,7 +42,7 @@
  private:
   scoped_refptr<const NGLayoutResult> Layout() final;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 
   void LayoutRowItems(ChildrenVector*,
                       LayoutUnit* max_row_block_baseline,
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
index 015829c..56a9d5e 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
@@ -408,7 +408,7 @@
 }
 
 MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& child_input) {
+    const MinMaxSizesInput& child_input) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h
index 6068ad8c..a238fcf8 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h
@@ -33,7 +33,7 @@
                       unsigned* first_prescript_index,
                       NGBoxFragmentBuilder* = nullptr) const;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 
   struct ChildAndMetrics {
     DISALLOW_NEW();
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
index 66f5d3c..7626e29 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
@@ -34,7 +34,7 @@
 }
 
 MinMaxSizesResult NGMathSpaceLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput&) {
+    const MinMaxSizesInput&) const {
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
           Node(), BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
index 466be22..5306bf4 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
@@ -20,7 +20,7 @@
  private:
   scoped_refptr<const NGLayoutResult> Layout() final;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) final;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
index d0d5619..7e78c350 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
@@ -326,7 +326,7 @@
 }
 
 MinMaxSizesResult NGMathUnderOverLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& child_input) {
+    const MinMaxSizesInput& child_input) const {
   DCHECK(IsValidMathMLScript(Node()));
 
   if (auto result = CalculateMinMaxSizesIgnoringChildren(
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
index a23dfb1..c5d7d93 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
@@ -20,7 +20,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
  private:
   void GatherChildren(NGBlockNode* base,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 3931d9e..86b569e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -230,7 +230,7 @@
 }
 
 MinMaxSizesResult NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   if (auto result =
           CalculateMinMaxSizesIgnoringChildren(node_, BorderScrollbarPadding()))
     return *result;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 1cf9cb7..e8c7571 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -62,7 +62,7 @@
 
   void SetBoxType(NGPhysicalFragment::NGBoxType type);
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
   scoped_refptr<const NGLayoutResult> Layout() override;
 
  private:
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
index 99c1829..d40de2a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
-#include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/text/writing_mode.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
@@ -68,6 +67,15 @@
         To<NGPhysicalBoxFragment>(physical_fragment_);
     return physical_box_fragment.Padding().ConvertToLogical(writing_direction_);
   }
+
+  bool HasDescendantsForTableCell() const {
+    const NGPhysicalBoxFragment& box_fragment =
+        To<NGPhysicalBoxFragment>(physical_fragment_);
+    DCHECK(box_fragment.IsTableNGCell());
+    return !box_fragment.Children().empty() ||
+           box_fragment.HasOutOfFlowPositionedFragmentainerDescendants() ||
+           box_fragment.HasOutOfFlowPositionedDescendants();
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index d1c999c7..4767ac3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -305,7 +305,7 @@
 }
 
 MinMaxSizesResult NGColumnLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   // First calculate the min/max sizes of columns.
   NGConstraintSpace space = CreateConstraintSpaceForMinMax();
   NGFragmentGeometry fragment_geometry =
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index 7515409..116963e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -26,7 +26,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
  private:
   // Lay out as many children as we can. If |kNeedsEarlierBreak| is returned, it
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index 607a778..86c79ff9 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -360,7 +360,7 @@
 }
 
 MinMaxSizesResult NGFieldsetLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   MinMaxSizesResult result;
 
   bool apply_size_containment = Node().ShouldApplySizeContainment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
index 6bbdb32..d8f42ef2 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
@@ -25,7 +25,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
   static LayoutUnit ComputeLegendInlineOffset(
       const ComputedStyle& legend_style,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
index b2c6a641..0588bca 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
@@ -32,7 +32,8 @@
   // Computes the min-content and max-content intrinsic sizes for the given box.
   // The result will not take any min-width, max-width or width properties into
   // account.
-  virtual MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) = 0;
+  virtual MinMaxSizesResult ComputeMinMaxSizes(
+      const MinMaxSizesInput&) const = 0;
 };
 
 // Parameters to pass when creating a layout algorithm for a block node.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
index 57880ef..39a001b9e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -69,7 +69,7 @@
 }
 
 MinMaxSizesResult NGPageLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   NGFragmentGeometry fragment_geometry =
       CalculateInitialMinMaxFragmentGeometry(ConstraintSpace(), Node());
   NGBlockLayoutAlgorithm algorithm(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
index acab80d7..d8613b6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
@@ -25,7 +25,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
  private:
   NGConstraintSpace CreateConstraintSpaceForPages(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
index 9adc7e13..e80a855 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
@@ -43,7 +43,7 @@
                               const NGLayoutResult&);
 
   scoped_refptr<const NGLayoutResult> Layout() override;
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override {
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override {
     NOTREACHED();
     return {MinMaxSizes(), /* depends_on_percentage_block_size */ true};
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
index c944f36..7c2672d3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
@@ -30,7 +30,7 @@
                                  bool is_new_fragment);
 
   scoped_refptr<const NGLayoutResult> Layout() override;
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override {
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override {
     NOTREACHED();
     return {MinMaxSizes(), /* depends_on_percentage_block_size */ true};
   }
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index 97ee6d7..7619fe8 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -570,7 +570,7 @@
 }
 
 MinMaxSizesResult NGTableLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput& input) {
+    const MinMaxSizesInput& input) const {
   LayoutNGTable* layout_table = To<LayoutNGTable>(Node().GetLayoutBox());
   const bool is_fixed_layout = Style().IsFixedTableLayout();
   // Tables need autosizer.
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.h
index 1d2314e..a525aeb 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.h
@@ -25,7 +25,7 @@
       : NGLayoutAlgorithm(params) {}
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 
   static LayoutUnit ComputeTableInlineSize(const NGTableNode& node,
                                            const NGConstraintSpace& space,
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
index ca46c88a..68f8009 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
@@ -568,7 +568,8 @@
     const bool is_baseline_aligned,
     const bool is_parallel,
     const bool descendant_depends_on_percentage_block_size) {
-  if (is_parallel && is_baseline_aligned) {
+  if (is_parallel && is_baseline_aligned &&
+      fragment.HasDescendantsForTableCell()) {
     max_cell_baseline_depends_on_percentage_block_descendant_ |=
         descendant_depends_on_percentage_block_size;
     const LayoutUnit cell_baseline = fragment.FirstBaselineOrSynthesize();
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
index e6478e1..be9bc61 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.cc
@@ -19,7 +19,7 @@
     : NGLayoutAlgorithm(params) {}
 
 MinMaxSizesResult NGTableRowLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput&) {
+    const MinMaxSizesInput&) const {
   NOTREACHED();  // Table layout does not compute minmax for table row.
   return MinMaxSizesResult();
 }
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.h
index 40208990d..e6d8502c 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.h
@@ -23,7 +23,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
index 461640a0..4e294d22 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.cc
@@ -16,7 +16,7 @@
     : NGLayoutAlgorithm(params) {}
 
 MinMaxSizesResult NGTableSectionLayoutAlgorithm::ComputeMinMaxSizes(
-    const MinMaxSizesInput&) {
+    const MinMaxSizesInput&) const {
   NOTREACHED();  // Table layout does not compute minmax for table row.
   return MinMaxSizesResult();
 }
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.h
index cf7dda1c..0ecbb790 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.h
@@ -23,7 +23,7 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
-  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) override;
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_loader_test.cc b/third_party/blink/renderer/core/loader/frame_loader_test.cc
index 84064ab..9cae016 100644
--- a/third_party/blink/renderer/core/loader/frame_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader_test.cc
@@ -6,7 +6,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/html/html_anchor_element.h"
 #include "third_party/blink/renderer/core/page/chrome_client_impl.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
index 4f31cfa..04436fc 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium AUthors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this sink code is governed by a BSD-style license that can be found
 // in the LICENSE file.
 
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 318a8eb2..f012a877 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -67,9 +67,9 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/forms/color_chooser.h"
 #include "third_party/blink/renderer/core/html/forms/color_chooser_client.h"
@@ -545,13 +545,13 @@
 void ChromeClientImpl::SetToolTip(LocalFrame& frame,
                                   const String& tooltip_text,
                                   TextDirection dir) {
-  WebFrameWidgetBase* widget =
+  WebFrameWidgetImpl* widget =
       WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
   if (!tooltip_text.IsEmpty()) {
     widget->SetToolTipText(tooltip_text, dir);
     did_request_non_empty_tool_tip_ = true;
   } else if (did_request_non_empty_tool_tip_) {
-    // WebFrameWidgetBase::SetToolTipText will send a Mojo message via
+    // WebFrameWidgetImpl::SetToolTipText will send a Mojo message via
     // mojom::blink::WidgetHost. We'd like to reduce the number of
     // SetToolTipText calls.
     widget->SetToolTipText(tooltip_text, dir);
@@ -712,7 +712,7 @@
 void ChromeClientImpl::AutoscrollStart(const gfx::PointF& viewport_point,
                                        LocalFrame* local_frame) {
   // TODO(dcheng): Why is this null check necessary?
-  if (WebFrameWidgetBase* widget =
+  if (WebFrameWidgetImpl* widget =
           WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
     widget->AutoscrollStart(viewport_point);
 }
@@ -720,14 +720,14 @@
 void ChromeClientImpl::AutoscrollFling(const gfx::Vector2dF& velocity,
                                        LocalFrame* local_frame) {
   // TODO(dcheng): Why is this null check necessary?
-  if (WebFrameWidgetBase* widget =
+  if (WebFrameWidgetImpl* widget =
           WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
     widget->AutoscrollFling(velocity);
 }
 
 void ChromeClientImpl::AutoscrollEnd(LocalFrame* local_frame) {
   // TODO(dcheng): Why is this null check necessary?
-  if (WebFrameWidgetBase* widget =
+  if (WebFrameWidgetImpl* widget =
           WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
     widget->AutoscrollEnd();
 }
@@ -932,7 +932,7 @@
   if (!frame)
     return cc::EventListenerProperties::kNone;
 
-  WebFrameWidgetBase* widget =
+  WebFrameWidgetImpl* widget =
       WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
   if (!widget)
     return cc::EventListenerProperties::kNone;
@@ -979,7 +979,7 @@
                                                bool needs_low_latency) {
   DCHECK(frame);
   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
-  WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
+  WebFrameWidgetImpl* widget = web_frame->LocalRootFrameWidget();
   if (!widget)
     return;
 
@@ -990,7 +990,7 @@
                                                           bool unbuffered) {
   DCHECK(frame);
   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
-  WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
+  WebFrameWidgetImpl* widget = web_frame->LocalRootFrameWidget();
   if (!widget)
     return;
 
@@ -1000,7 +1000,7 @@
 void ChromeClientImpl::RequestUnbufferedInputEvents(LocalFrame* frame) {
   DCHECK(frame);
   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
-  WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
+  WebFrameWidgetImpl* widget = web_frame->LocalRootFrameWidget();
   if (!widget)
     return;
 
@@ -1011,7 +1011,7 @@
                                       TouchAction touch_action) {
   DCHECK(frame);
   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
-  WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
+  WebFrameWidgetImpl* widget = web_frame->LocalRootFrameWidget();
   if (!widget)
     return;
 
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc
index 9339db3..699c2e3 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -52,7 +52,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
diff --git a/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
index fe81f72..991098c 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller_test.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -15,7 +15,7 @@
 #include "third_party/blink/renderer/core/dom/xml_document.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
index 82e8b75..6e8bdc1 100644
--- a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 9c38f45..7705163 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -19,7 +19,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
index 4d00f41..6524611d 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -48,7 +48,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/html/html_object_element.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
index acfc46a..3a9835b 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
@@ -20,11 +20,6 @@
 
 namespace {
 
-// Returns text content of the node, skipping invisible children and comments.
-String GetText(Node* node) {
-  return PlainText(EphemeralRange::RangeOfContents(*node));
-}
-
 // Returns true if text from beginning of |node| until |pos_offset| can be
 // considered empty. Otherwise, return false.
 bool IsFirstVisiblePosition(Node* node, unsigned pos_offset) {
@@ -76,7 +71,9 @@
   // Move forward/backward until non empty visible text node is found.
   for (Node* node = start_node; node; node = Direction::Next(*node)) {
     Node* next_node = Direction::GetVisibleTextNode(*node);
-    if (!next_node || !GetText(next_node).IsEmpty())
+    if (!next_node || !PlainText(EphemeralRange::RangeOfContents(*next_node))
+                           .StripWhiteSpace()
+                           .IsEmpty())
       return next_node;
     node = next_node;
   }
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
index 60aacea..03b97e75 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
@@ -717,6 +717,43 @@
   GenerateAndVerifySelector(start, end, "page-,First,-paragraph");
 }
 
+// Check the case when selections starts with a node nested in "inline-block"
+// node. crbug.com/1151474
+TEST_F(TextFragmentSelectorGeneratorTest, StartsWithInlineBlockChild) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      li {
+        display: inline-block;
+      }
+    </style>
+    <div>Test page</div>
+    <ul>
+      <li>
+        <a id="link1"/>
+      </li>
+      <li>
+        <a id="link2"/>
+      </li>
+      <li>
+        <a id="link3"/>
+      </li>
+    </ul>
+    <p id='first'>First paragraph text that is longer  than 20 chars</p>
+  )HTML");
+
+  GetDocument().View()->UpdateAllLifecyclePhasesForTest();
+  Node* img = GetDocument().getElementById("link1");
+  Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
+  const auto& start = Position(img, PositionAnchorType::kAfterChildren);
+  const auto& end = Position(first_paragraph, 5);
+  ASSERT_EQ("  \nFirst", PlainText(EphemeralRange(start, end)));
+
+  GenerateAndVerifySelector(start, end, "page-,First,-paragraph");
+}
+
 // Check the case when selections ends with an non text node.
 TEST_F(TextFragmentSelectorGeneratorTest, EndswithImage) {
   SimRequest request("https://example.com/test.html", "text/html");
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
index 29375afe..587e26a 100644
--- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -392,6 +392,24 @@
   return false;
 }
 
+static bool IsContentVisibilityAutoWithoutFirstIntersection(
+    const LayoutBox& box) {
+  if (!box.GetNode() || !box.GetNode()->IsElementNode())
+    return false;
+
+  auto* display_lock_context =
+      To<Element>(box.GetNode())->GetDisplayLockContext();
+  if (!display_lock_context)
+    return false;
+
+  if (!display_lock_context->IsLocked() ||
+      display_lock_context->HadAnyViewportIntersectionNotifications() ||
+      !display_lock_context->IsAuto())
+    return false;
+
+  return true;
+}
+
 bool BoxPaintInvalidator::NeedsToSavePreviousOverflowData() {
   if (box_.HasVisualOverflow() || box_.HasLayoutOverflow())
     return true;
@@ -412,7 +430,21 @@
 
 void BoxPaintInvalidator::SavePreviousBoxGeometriesIfNeeded() {
   auto mutable_box = box_.GetMutableForPainting();
-  mutable_box.SavePreviousSize();
+  // If a box has content-visibility:auto and has not yet been deemed to be near
+  // the viewport, then don't save its previous size. This prevents the
+  // LayoutShiftTracker (which computes CLS) from recording a layout shift when
+  // the element's subtree become unskipped for the first time. This is almost
+  // exactly equivalent to the current behavior of CLS computation for offscreen
+  // elements - i.e. those elements are not counted for CLS. The only difference
+  // is the one-frame leeway granted after box_ appears near the screen.
+  //
+  // Note: The downside of this approach is that any change in size of |box_|
+  // up to the time unskipping occurs will cause a full paint invalidation
+  // of |box_|. Since this has no effect on its subtree (which is skipped),
+  // and |box_| is not on-screen, this should not have a significant performance
+  // impact.
+  if (!IsContentVisibilityAutoWithoutFirstIntersection(box_))
+    mutable_box.SavePreviousSize();
 
   if (NeedsToSavePreviousOverflowData())
     mutable_box.SavePreviousOverflowData();
diff --git a/third_party/blink/renderer/core/paint/element_timing_utils.cc b/third_party/blink/renderer/core/paint/element_timing_utils.cc
index 585578a8..1eeee2b 100644
--- a/third_party/blink/renderer/core/paint/element_timing_utils.cc
+++ b/third_party/blink/renderer/core/paint/element_timing_utils.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/core/paint/element_timing_utils.h"
 
 #include "third_party/blink/public/web/web_widget_client.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -27,7 +27,7 @@
                                                 ->FirstFragment()
                                                 .LocalBorderBoxProperties(),
                                             visual_rect);
-  WebFrameWidgetBase* widget =
+  WebFrameWidgetImpl* widget =
       WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
   DCHECK(widget);
   return FloatRect(widget->BlinkSpaceToDIPs(visual_rect.Rect()));
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index f987f72..666a9cf 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -42,7 +42,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index c8de5d9..c236c868 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -538,9 +538,9 @@
     const PhysicalOffset& paint_offset,
     bool suppress_box_decoration_background) {
   const PaintPhase paint_phase = paint_info.phase;
-  const NGPhysicalBoxFragment& physical_box_fragment = PhysicalFragment();
-  const ComputedStyle& style = box_fragment_.Style();
-  bool is_visible = IsVisibleToPaint(physical_box_fragment, style);
+  const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+  const ComputedStyle& style = fragment.Style();
+  bool is_visible = IsVisibleToPaint(fragment, style);
   if (ShouldPaintSelfBlockBackground(paint_phase)) {
     if (is_visible) {
       PaintBoxDecorationBackground(paint_info, paint_offset,
@@ -558,21 +558,20 @@
 
   if (paint_phase == PaintPhase::kForeground) {
     if (paint_info.ShouldAddUrlMetadata()) {
-      NGFragmentPainter(box_fragment_, GetDisplayItemClient())
+      NGFragmentPainter(fragment, GetDisplayItemClient())
           .AddURLRectIfNeeded(paint_info, paint_offset);
     }
-    if (is_visible && box_fragment_.HasExtraMathMLPainting())
-      NGMathMLPainter(box_fragment_).Paint(paint_info, paint_offset);
+    if (is_visible && fragment.HasExtraMathMLPainting())
+      NGMathMLPainter(fragment).Paint(paint_info, paint_offset);
   }
 
   // Paint children.
   if (paint_phase != PaintPhase::kSelfOutlineOnly &&
-      (!physical_box_fragment.Children().empty() ||
-       physical_box_fragment.HasItems() || inline_box_cursor_) &&
+      (!fragment.Children().empty() || fragment.HasItems() ||
+       inline_box_cursor_) &&
       !paint_info.DescendantPaintingBlocked()) {
     if (is_visible && UNLIKELY(paint_phase == PaintPhase::kForeground &&
-                               box_fragment_.IsCSSBox() &&
-                               box_fragment_.Style().HasColumnRule()))
+                               fragment.IsCSSBox() && style.HasColumnRule()))
       PaintColumnRules(paint_info, paint_offset);
 
     if (paint_phase != PaintPhase::kFloat) {
@@ -589,15 +588,15 @@
                          paint_offset_to_inline_formatting_context,
                          box_item_->OffsetInContainerBlock(), &descendants);
       } else if (items_) {
-        if (physical_box_fragment.IsBlockFlow()) {
+        if (fragment.IsBlockFlow()) {
           PaintBlockFlowContents(paint_info, paint_offset);
         } else {
-          DCHECK(physical_box_fragment.IsInlineBox());
-          NGInlineCursor cursor(physical_box_fragment, *items_);
+          DCHECK(fragment.IsInlineBox());
+          NGInlineCursor cursor(fragment, *items_);
           PaintInlineItems(paint_info.ForDescendants(), paint_offset,
                            PhysicalOffset(), &cursor);
         }
-      } else if (!physical_box_fragment.IsInlineFormattingContext()) {
+      } else if (!fragment.IsInlineFormattingContext()) {
         PaintBlockChildren(paint_info, paint_offset);
       } else if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
         // This is the NGPaintFragment code path. We need the check for
@@ -624,7 +623,7 @@
         // the remaining 50px of #fl - no items (all in-flow content fits in the
         // first fragment).
         DCHECK(paint_fragment_);
-        if (physical_box_fragment.IsBlockFlow()) {
+        if (fragment.IsBlockFlow()) {
           PaintBlockFlowContents(paint_info, paint_offset);
         } else if (ShouldPaintDescendantOutlines(paint_info.phase)) {
           // TODO(kojii): |PaintInlineChildrenOutlines()| should do the work
@@ -642,13 +641,13 @@
     if (paint_phase == PaintPhase::kFloat ||
         paint_phase == PaintPhase::kSelectionDragImage ||
         paint_phase == PaintPhase::kTextClip) {
-      if (physical_box_fragment.HasFloatingDescendantsForPaint())
+      if (fragment.HasFloatingDescendantsForPaint())
         PaintFloats(paint_info);
     }
   }
 
   if (is_visible && ShouldPaintSelfOutline(paint_phase)) {
-    NGFragmentPainter(box_fragment_, GetDisplayItemClient())
+    NGFragmentPainter(fragment, GetDisplayItemClient())
         .PaintOutline(paint_info, paint_offset);
   }
 }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index c3cc16c49d6..5851f84 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -908,8 +908,10 @@
   // inline parent to find the actual containing layer through the containing
   // block chain.
   // Column span need to find the containing layer through its containing block.
+  // A rendered legend needs to find the containing layer through its containing
+  // block to skip anonymous fieldset content box.
   if ((!Parent() || Parent()->GetLayoutObject().IsLayoutBlock()) &&
-      !layout_object.IsColumnSpanAll())
+      !layout_object.IsColumnSpanAll() && !layout_object.IsRenderedLegend())
     return Parent();
 
   // This is a universal approach to find containing layer, but is slower than
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
index 4b0784a..6eb858c 100644
--- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc
+++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -7,7 +7,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
index 72b0bb1..def5e9d8 100644
--- a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
+++ b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
@@ -15,7 +15,7 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -1695,7 +1695,7 @@
   intersection.main_frame_viewport_size = gfx::Size(100, 100);
   intersection.viewport_intersection = gfx::Rect(0, 0, 100, 100);
   LocalFrameRoot().FrameWidget()->Resize(gfx::Size(300, 200));
-  static_cast<WebFrameWidgetBase*>(LocalFrameRoot().FrameWidget())
+  static_cast<WebFrameWidgetImpl*>(LocalFrameRoot().FrameWidget())
       ->SetViewportIntersection(intersection.Clone());
 
   auto* root_frame = LocalFrameRoot().GetFrame();
@@ -1736,7 +1736,7 @@
 
   // Show the frame without any other change.
   LocalFrameRoot().WasShown();
-  static_cast<WebFrameWidgetBase*>(LocalFrameRoot().FrameWidget())
+  static_cast<WebFrameWidgetImpl*>(LocalFrameRoot().FrameWidget())
       ->SetViewportIntersection(intersection.Clone());
   CompositeFrame();
   EXPECT_EQ(root_frame->RemoteViewportIntersection(), IntRect(0, 0, 100, 100));
diff --git a/third_party/blink/renderer/core/streams/readable_byte_stream_controller.h b/third_party/blink/renderer/core/streams/readable_byte_stream_controller.h
index 348a6a2..84d1e38 100644
--- a/third_party/blink/renderer/core/streams/readable_byte_stream_controller.h
+++ b/third_party/blink/renderer/core/streams/readable_byte_stream_controller.h
@@ -1,4 +1,4 @@
-// Copyright 2020 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.
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_byob_reader.h b/third_party/blink/renderer/core/streams/readable_stream_byob_reader.h
index 198e915c..1d9d421 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_byob_reader.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_byob_reader.h
@@ -1,4 +1,4 @@
-// Copyright 2020 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.
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_byob_request.h b/third_party/blink/renderer/core/streams/readable_stream_byob_request.h
index 834e17f..7f65ecaf 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_byob_request.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_byob_request.h
@@ -1,4 +1,4 @@
-// Copyright 2020 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.
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_controller.h b/third_party/blink/renderer/core/streams/readable_stream_controller.h
index b8161c1..080c33a 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_controller.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_controller.h
@@ -1,4 +1,4 @@
-// Copyright 2020 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.
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h b/third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h
index fee43c4..aafe8a2 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h
@@ -1,4 +1,4 @@
-// Copyright 2020 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.
 
diff --git a/third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h b/third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h
index a5858b8..d6e34461 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h
+++ b/third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium AUthors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this sink code is governed by a BSD-style license that can be found
 // in the LICENSE file.
 
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.cc b/third_party/blink/renderer/core/timing/performance_user_timing.cc
index e4aa7826..05da2ae 100644
--- a/third_party/blink/renderer/core/timing/performance_user_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -42,11 +42,11 @@
   PerformanceEntryMap::iterator it = performance_entry_map.find(entry.name());
   if (it != performance_entry_map.end()) {
     DCHECK(it->value);
-    it->value->push_back(entry);
+    it->value->push_back(&entry);
   } else {
     PerformanceEntryVector* vector =
         MakeGarbageCollected<PerformanceEntryVector>();
-    vector->push_back(entry);
+    vector->push_back(&entry);
     performance_entry_map.Set(entry.name(), vector);
   }
 }
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 7039690..b4a46af 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -30,7 +30,7 @@
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
 #include "third_party/blink/renderer/core/loader/appcache/application_cache_host.h"
@@ -281,7 +281,7 @@
   if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
     LocalFrame* frame = window->GetFrame();
     if (frame) {
-      WebFrameWidgetBase* widget =
+      WebFrameWidgetImpl* widget =
           WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
       begin_frame_provider_params.parent_frame_sink_id =
           widget->GetFrameSinkId();
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc
index 21803ad..e1c7349 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc
@@ -10,7 +10,7 @@
 #include "base/timer/elapsed_timer.h"
 #include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
 #include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
diff --git a/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
index 9ad2aa3..a9b42d2 100644
--- a/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
+++ b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/modules/csspaint/native_paint_worklet.h"
 
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/modules/csspaint/native_paint_worklet_proxy_client.h"
 #include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
index 8620797..a4b74508 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
@@ -12,7 +12,7 @@
 #include "third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h"
 #include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
index 7e80f41..ecc741c 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -521,8 +521,7 @@
       track_id, MediaStreamSource::kTypeVideo, track_id, false);
   stream_source->SetPlatformSource(std::move(stream_video_source));
   stream_source->SetCapabilities(ComputeCapabilitiesForVideoSource(
-      track_id, preferred_formats,
-      media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
+      track_id, preferred_formats, mojom::blink::FacingMode::NONE,
       false /* is_device_capture */));
 
   *component = MakeGarbageCollected<MediaStreamComponent>(stream_source);
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
index ab28328..46f9ad4 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.h"
 
 #include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
@@ -63,8 +64,7 @@
       track_id, MediaStreamSource::kTypeVideo, track_id, is_remote);
   media_stream_source->SetPlatformSource(std::move(media_stream_video_source));
   media_stream_source->SetCapabilities(ComputeCapabilitiesForVideoSource(
-      track_id, preferred_formats,
-      media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
+      track_id, preferred_formats, mojom::blink::FacingMode::NONE,
       false /* is_device_capture */));
   descriptor->AddRemoteTrack(MediaStreamVideoTrack::CreateVideoTrack(
       media_stream_video_source_ptr,
diff --git a/third_party/blink/renderer/modules/mediasource/BUILD.gn b/third_party/blink/renderer/modules/mediasource/BUILD.gn
index b3b7d11e..9c68bae7 100644
--- a/third_party/blink/renderer/modules/mediasource/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediasource/BUILD.gn
@@ -35,4 +35,8 @@
     "video_playback_quality.cc",
     "video_playback_quality.h",
   ]
+  deps = [
+    # Ensure the generated webcodecs v8 config and chunk bindings are available.
+    "//third_party/blink/renderer/modules/webcodecs:webcodecs",
+  ]
 }
diff --git a/third_party/blink/renderer/modules/mediasource/DEPS b/third_party/blink/renderer/modules/mediasource/DEPS
index d96729c3..bc507951 100644
--- a/third_party/blink/renderer/modules/mediasource/DEPS
+++ b/third_party/blink/renderer/modules/mediasource/DEPS
@@ -4,4 +4,5 @@
     "+third_party/blink/renderer/modules/event_modules.h",
     "+third_party/blink/renderer/modules/event_target_modules.h",
     "+third_party/blink/renderer/modules/mediasource",
+    "+third_party/blink/renderer/modules/webcodecs",
 ]
diff --git a/third_party/blink/renderer/modules/mediasource/idls.gni b/third_party/blink/renderer/modules/mediasource/idls.gni
index 5ebc2d32..5dfa8b3e 100644
--- a/third_party/blink/renderer/modules/mediasource/idls.gni
+++ b/third_party/blink/renderer/modules/mediasource/idls.gni
@@ -11,6 +11,8 @@
   "video_playback_quality.idl",
 ]
 
+modules_dictionary_idl_files = [ "source_buffer_config.idl" ]
+
 modules_dependency_idl_files = [
   "audio_track_source_buffer.idl",
   "html_video_element_media_source.idl",
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index 19da60e1..cf9ca546 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -14,6 +14,9 @@
 #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
 #include "third_party/blink/public/platform/web_media_source.h"
 #include "third_party/blink/public/platform/web_source_buffer.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/events/event_queue.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
@@ -218,6 +221,18 @@
   return source_buffer;
 }
 
+SourceBuffer* MediaSource::AddSourceBufferUsingConfig(
+    const SourceBufferConfig* config,
+    ExceptionState& exception_state) {
+  DVLOG(2) << __func__ << " this=" << this;
+  // TODO(crbug.com/1144908): Validate allowed in current state (and take lock
+  // at appropriate point), unwrap the config, validate it, create sourcebuffer,
+  // etc.
+  exception_state.ThrowTypeError(
+      "unimplemented - see https://crbug.com/1144908");
+  return nullptr;
+}
+
 void MediaSource::AddSourceBuffer_Locked(
     const String& type,
     ExceptionState* exception_state,
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.h b/third_party/blink/renderer/modules/mediasource/media_source.h
index 1159c58..7198882 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -31,6 +31,7 @@
 class HTMLMediaElement;
 class CrossThreadMediaSourceAttachment;
 class SameThreadMediaSourceAttachment;
+class SourceBufferConfig;
 class TrackBase;
 class WebSourceBuffer;
 
@@ -67,6 +68,9 @@
   }
   SourceBuffer* addSourceBuffer(const String& type, ExceptionState&)
       LOCKS_EXCLUDED(attachment_link_lock_);
+  SourceBuffer* AddSourceBufferUsingConfig(const SourceBufferConfig*,
+                                           ExceptionState&)
+      LOCKS_EXCLUDED(attachment_link_lock_);
   void removeSourceBuffer(SourceBuffer*, ExceptionState&)
       LOCKS_EXCLUDED(attachment_link_lock_);
   void setDuration(double, ExceptionState&)
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.idl b/third_party/blink/renderer/modules/mediasource/media_source.idl
index b09078e..161f0b1f 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.idl
+++ b/third_party/blink/renderer/modules/mediasource/media_source.idl
@@ -50,7 +50,18 @@
     attribute EventHandler onsourceopen;
     attribute EventHandler onsourceended;
     attribute EventHandler onsourceclose;
+
     [RaisesException] SourceBuffer addSourceBuffer(DOMString type);
+
+    // For MSE-for-WebCodecs. Explainer:
+    // https://github.com/wolenetz/mse-for-webcodecs/blob/main/explainer.md
+    [
+        RaisesException,
+        RuntimeEnabled=MediaSourceExtensionsForWebCodecs,
+        ImplementedAs=AddSourceBufferUsingConfig,
+        MeasureAs=AddSourceBufferUsingConfig
+    ] SourceBuffer addSourceBuffer(SourceBufferConfig config);
+
     [RaisesException] void removeSourceBuffer(SourceBuffer buffer);
     readonly attribute DOMString readyState;
     [RaisesException] void endOfStream(optional EndOfStreamError error);
@@ -58,7 +69,9 @@
     [RaisesException] void setLiveSeekableRange(double start, double end);
     [RaisesException] void clearLiveSeekableRange();
 
-    [CallWith=ExecutionContext] static boolean isTypeSupported (DOMString type);
+    // TODO(crbug.com/1144908): Consider adding an overload which is given a
+    // SourceBufferConfig.
+    [CallWith=ExecutionContext] static boolean isTypeSupported(DOMString type);
 
     // Enables proactive feature-detection of MSE-in-Workers support from the
     // main thread (or anywhere this interface is exposed.) If the attribute is
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.cc b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
index e370a4ba..1f73297a 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -38,6 +38,10 @@
 #include "media/base/logging_override_if_enabled.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_source_buffer.h"
+#include "third_party/blink/renderer/bindings/modules/v8/encoded_av_chunk_sequence_or_encoded_av_chunk.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_source_buffer_config.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/events/event_queue.h"
@@ -53,6 +57,8 @@
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
 #include "third_party/blink/renderer/modules/mediasource/media_source.h"
 #include "third_party/blink/renderer/modules/mediasource/source_buffer_track_base_supplement.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h"
+#include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
@@ -316,8 +322,9 @@
   // 3. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // Do the remainder of steps only if attachment is usable and underlying
   // demuxer is protected from destruction (applicable especially for
@@ -404,8 +411,9 @@
   // 2. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // 3. If the new value is less than 0 or greater than or equal to
   //    appendWindowEnd then throw a TypeError exception and abort these steps.
@@ -460,8 +468,9 @@
   // 2. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // 3. If the new value equals NaN, then throw a TypeError and abort these
   //    steps.
@@ -526,6 +535,31 @@
       data.View()->byteLength(), exception_state);
 }
 
+ScriptPromise SourceBuffer::appendEncodedChunks(
+    ScriptState* script_state,
+    const EncodedChunks& chunks,
+    ExceptionState& exception_state) {
+  // Note that |chunks| may be a sequence of mixed audio and video encoded
+  // chunks (which should cause underlying buffering validation to emit error
+  // akin to appending video to an audio track or vice-versa). It was impossible
+  // to get the bindings generator to disambiguate sequence<audio> vs
+  // sequence<video>, hence we could not use simple overloading in the IDL for
+  // these two. Neither could the IDL union attempt similar. We must enforce
+  // that semantic in implementation. Further note, |chunks| may instead be a
+  // single audio or a single video chunk as a helpful additional overload for
+  // one-chunk-at-a-time append use-cases.
+
+  DVLOG(2) << __func__ << " this=" << this;
+
+  // TODO(crbug.com/1144908): Validate allowed in current state (and take lock
+  // at appropriate point), unwrap the chunks, get a promise and its resolver,
+  // give the resolver to the async validation and buffering of the chunks,
+  // return the promise.
+  exception_state.ThrowTypeError(
+      "unimplemented - see https://crbug.com/1144908");
+  return ScriptPromise();
+}
+
 void SourceBuffer::abort(ExceptionState& exception_state) {
   DVLOG(2) << __func__ << " this=" << this;
   // http://w3c.github.io/media-source/#widl-SourceBuffer-abort-void
@@ -620,8 +654,9 @@
   // 2. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // Do remainder of steps only if attachment is usable and underlying demuxer
   // is protected from destruction (applicable especially for MSE-in-Worker
@@ -722,8 +757,9 @@
   // 3. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // Do remainder of steps only if attachment is usable and underlying demuxer
   // is protected from destruction (applicable especially for MSE-in-Worker
@@ -740,6 +776,39 @@
   }
 }
 
+void SourceBuffer::ChangeTypeUsingConfig(const SourceBufferConfig* config,
+                                         ExceptionState& exception_state) {
+  DVLOG(2) << __func__ << " this=" << this;
+
+  // If this object has been removed from the sourceBuffers attribute of the
+  //    parent media source, then throw an InvalidStateError exception and abort
+  //    these steps.
+  // If the updating attribute equals true, then throw an InvalidStateError
+  //    exception and abort these steps.
+  if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
+                                        exception_state)) {
+    return;
+  }
+
+  // Before this IDL overload was added, changeType(null) yielded a
+  // kNotSupportedError, so preserve that behavior if the bindings resolve us
+  // instead of the original changeType(DOMString) when given a null parameter.
+  // Fortunately, a null or empty SourceBufferConfig here similarly should yield
+  // a kNotSupportedError.
+  if (!config || (!config->hasAudioConfig() && !config->hasVideoConfig())) {
+    MediaSource::LogAndThrowDOMException(
+        exception_state, DOMExceptionCode::kNotSupportedError,
+        "Changing to the type provided ('null' config) is not supported.");
+    return;
+  }
+
+  // TODO(crbug.com/1144908): Further validate allowed in current state (and
+  // take lock at appropriate point), unwrap the config, validate it, update
+  // internals to new config, etc.
+  exception_state.ThrowTypeError(
+      "unimplemented - see https://crbug.com/1144908");
+}
+
 void SourceBuffer::ChangeType_Locked(
     const String& type,
     ExceptionState* exception_state,
@@ -806,8 +875,9 @@
   // 2. If the updating attribute equals true, then throw an InvalidStateError
   //    exception and abort these steps.
   if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
-                                        exception_state))
+                                        exception_state)) {
     return;
+  }
 
   // 3. Update the attribute to the new value.
   track_defaults_ = track_defaults;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.h b/third_party/blink/renderer/modules/mediasource/source_buffer.h
index 686117d1..a9343370 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.h
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.h
@@ -36,6 +36,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/web_source_buffer_client.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
@@ -50,11 +51,15 @@
 class AudioTrackList;
 class DOMArrayBuffer;
 class DOMArrayBufferView;
+class
+    EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk;
 class EventQueue;
 class ExceptionState;
 class MediaSource;
 class MediaSourceTracer;
 class MediaSourceAttachmentSupplement;
+class ScriptState;
+class SourceBufferConfig;
 class TimeRanges;
 class VideoTrackList;
 class WebSourceBuffer;
@@ -70,6 +75,10 @@
   static AtomicString SegmentsKeyword();
   static AtomicString SequenceKeyword();
 
+  // Mirror the IDL's typedef for EncodedChunks.
+  using EncodedChunks =
+      EncodedAudioChunkOrEncodedVideoChunkSequenceOrEncodedAudioChunkOrEncodedVideoChunk;
+
   SourceBuffer(std::unique_ptr<WebSourceBuffer>, MediaSource*, EventQueue*);
   ~SourceBuffer() override;
 
@@ -82,9 +91,13 @@
   void setTimestampOffset(double, ExceptionState&);
   void appendBuffer(DOMArrayBuffer* data, ExceptionState&);
   void appendBuffer(NotShared<DOMArrayBufferView> data, ExceptionState&);
+  ScriptPromise appendEncodedChunks(ScriptState*,
+                                    const EncodedChunks&,
+                                    ExceptionState&);
   void abort(ExceptionState&);
   void remove(double start, double end, ExceptionState&);
   void changeType(const String& type, ExceptionState&);
+  void ChangeTypeUsingConfig(const SourceBufferConfig*, ExceptionState&);
   double appendWindowStart() const;
   void setAppendWindowStart(double, ExceptionState&);
   double appendWindowEnd() const;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.idl b/third_party/blink/renderer/modules/mediasource/source_buffer.idl
index 04c0634f..5bcbbdc 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.idl
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.idl
@@ -30,6 +30,10 @@
 
 // https://w3c.github.io/media-source/#idl-def-sourcebuffer
 
+// This typedef is needed for MSE-for-WebCodecs. Explainer:
+// https://github.com/wolenetz/mse-for-webcodecs/blob/main/explainer.md
+typedef (sequence<(EncodedAudioChunk or EncodedVideoChunk)> or EncodedAudioChunk or EncodedVideoChunk) EncodedChunks;
+
 enum AppendMode {
     "segments",
     "sequence"
@@ -70,6 +74,15 @@
     [RaisesException] void appendBuffer(ArrayBuffer data);
     [RaisesException] void appendBuffer(ArrayBufferView data);
 
+    // Append WebCodecs structured, "containerless" media. Explainer:
+    // https://github.com/wolenetz/mse-for-webcodecs/blob/main/explainer.md
+    [
+        CallWith=ScriptState,
+        RaisesException,
+        RuntimeEnabled=MediaSourceExtensionsForWebCodecs,
+        Measure
+    ] Promise<void> appendEncodedChunks(EncodedChunks chunks);
+
     // Abort the current segment append sequence.
     [RaisesException] void abort();
     [RaisesException] void remove(double start, unrestricted double end);
@@ -77,6 +90,15 @@
     // Explicitly change the container or codecs
     [RaisesException, Measure] void changeType(DOMString type);
 
+    // For MSE-for-WebCodecs. Explainer:
+    // https://github.com/wolenetz/mse-for-webcodecs/blob/main/explainer.md
+    [
+      RaisesException,
+      RuntimeEnabled=MediaSourceExtensionsForWebCodecs,
+      ImplementedAs=ChangeTypeUsingConfig,
+      MeasureAs=ChangeTypeUsingConfig
+    ] void changeType(SourceBufferConfig config);
+
     // Gets or sets the TrackDefaultList this SourceBuffer may consult during
     // the initialization segment algorithm.
     [RaisesException=Setter, RuntimeEnabled=MediaSourceExperimental] attribute TrackDefaultList trackDefaults;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_config.idl b/third_party/blink/renderer/modules/mediasource/source_buffer_config.idl
new file mode 100644
index 0000000..5711e02
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer_config.idl
@@ -0,0 +1,18 @@
+// 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
+
+// For MSE-for-WebCodecs. Explainer:
+// https://github.com/wolenetz/mse-for-webcodecs/blob/main/explainer.md
+
+dictionary SourceBufferConfig {
+  // Precisely one of these must be populated to signal via addSourceBuffer or
+  // changeType the intent to buffer the corresponding WebCodecs media.
+  // We use this dictionary as the parameter for SourceBuffer's overloads of
+  // addSourceBuffer() and changeType() since sniffing config types introduces
+  // implementation interoperability risk, and specific overloads for each of
+  // AudioDecoderConfig and VideoDecoderConfig dictionaries would not be
+  // differentiable without such sniffing.
+  AudioDecoderConfig audioConfig;  // For appending EncodedAudioChunks.
+  VideoDecoderConfig videoConfig;  // For appending EncodedVideoChunks.
+};
diff --git a/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc b/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
index 38b6d77..c5a4d77a 100644
--- a/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
@@ -249,8 +249,10 @@
   device_capabilities.device_id = current_request_->Track()->Source()->Id();
   device_capabilities.group_id = current_request_->Track()->Source()->GroupId();
   device_capabilities.facing_mode =
-      GetCurrentVideoSource() ? GetCurrentVideoSource()->device().video_facing
-                              : media::MEDIA_VIDEO_FACING_NONE;
+      GetCurrentVideoSource()
+          ? static_cast<mojom::blink::FacingMode>(
+                GetCurrentVideoSource()->device().video_facing)
+          : mojom::blink::FacingMode::NONE;
   device_capabilities.formats = std::move(formats);
 
   blink::VideoDeviceCaptureCapabilities video_capabilities;
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index 2ba40cc..796d3b2 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -89,13 +89,13 @@
             mojom::blink::VideoInputDeviceCapabilities::New();
         capabilities->device_id = kFakeVideoInputDeviceId1;
         capabilities->group_id = kFakeCommonGroupId1;
-        capabilities->facing_mode = media::MEDIA_VIDEO_FACING_NONE;
+        capabilities->facing_mode = mojom::blink::FacingMode::NONE;
         video_input_capabilities.push_back(std::move(capabilities));
 
         capabilities = mojom::blink::VideoInputDeviceCapabilities::New();
         capabilities->device_id = kFakeVideoInputDeviceId2;
         capabilities->group_id = kFakeVideoInputGroupId2;
-        capabilities->facing_mode = media::MEDIA_VIDEO_FACING_USER;
+        capabilities->facing_mode = mojom::blink::FacingMode::USER;
         video_input_capabilities.push_back(std::move(capabilities));
       }
     }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
index 9f300df..a8690e8 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc
@@ -281,7 +281,7 @@
 MediaStreamSource::Capabilities ComputeCapabilitiesForVideoSource(
     const String& device_id,
     const media::VideoCaptureFormats& formats,
-    media::VideoFacingMode facing_mode,
+    mojom::blink::FacingMode facing_mode,
     bool is_device_capture,
     const base::Optional<std::string>& group_id) {
   MediaStreamSource::Capabilities capabilities;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
index 5ec959eb..a57535f 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h
@@ -9,6 +9,7 @@
 
 #include "media/base/video_facing.h"
 #include "media/capture/video_capture_types.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
 #include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h"
 #include "third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -339,7 +340,7 @@
 ComputeCapabilitiesForVideoSource(
     const String& device_id,
     const media::VideoCaptureFormats& formats,
-    media::VideoFacingMode facing_mode,
+    mojom::blink::FacingMode facing_mode,
     bool is_device_capture,
     const base::Optional<std::string>& group_id = base::nullopt);
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
index dcb574f..3a0631f 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
@@ -41,11 +41,11 @@
 const char kVideoKindColor[] = "color";
 const char kVideoKindDepth[] = "depth";
 
-WebString ToWebString(media::VideoFacingMode facing_mode) {
+WebString ToWebString(mojom::blink::FacingMode facing_mode) {
   switch (facing_mode) {
-    case media::MEDIA_VIDEO_FACING_USER:
+    case mojom::blink::FacingMode::USER:
       return WebString::FromASCII("user");
-    case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
+    case mojom::blink::FacingMode::ENVIRONMENT:
       return WebString::FromASCII("environment");
     default:
       return WebString();
@@ -430,7 +430,7 @@
 
 // Returns true if the facing mode |value| satisfies |constraints|, false
 // otherwise.
-bool FacingModeSatisfiesConstraint(media::VideoFacingMode value,
+bool FacingModeSatisfiesConstraint(mojom::blink::FacingMode value,
                                    const StringConstraint& constraint) {
   WebString string_value = ToWebString(value);
   if (string_value.IsNull())
@@ -693,7 +693,7 @@
     String group_id,
     const media::VideoCaptureControlSupport& control_support,
     Vector<media::VideoCaptureFormat> formats,
-    media::VideoFacingMode facing_mode)
+    mojom::blink::FacingMode facing_mode)
     : device_id(std::move(device_id)),
       group_id(std::move(group_id)),
       control_support(control_support),
@@ -714,13 +714,13 @@
 }
 
 MediaStreamTrackPlatform::FacingMode ToPlatformFacingMode(
-    media::VideoFacingMode video_facing) {
+    mojom::blink::FacingMode video_facing) {
   switch (video_facing) {
-    case media::MEDIA_VIDEO_FACING_NONE:
+    case mojom::blink::FacingMode::NONE:
       return MediaStreamTrackPlatform::FacingMode::kNone;
-    case media::MEDIA_VIDEO_FACING_USER:
+    case mojom::blink::FacingMode::USER:
       return MediaStreamTrackPlatform::FacingMode::kUser;
-    case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
+    case mojom::blink::FacingMode::ENVIRONMENT:
       return MediaStreamTrackPlatform::FacingMode::kEnvironment;
     default:
       return MediaStreamTrackPlatform::FacingMode::kNone;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
index ac8ffa0..096e15e 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
@@ -7,6 +7,7 @@
 
 #include "base/optional.h"
 #include "media/capture/video_capture_types.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
 #include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -25,7 +26,7 @@
 GetVideoKindForFormat(const media::VideoCaptureFormat& format);
 
 MODULES_EXPORT MediaStreamTrackPlatform::FacingMode ToPlatformFacingMode(
-    media::VideoFacingMode video_facing);
+    mojom::blink::FacingMode video_facing);
 
 // This is a temporary struct to bridge blink and content mojo types.
 struct MODULES_EXPORT VideoInputDeviceCapabilities {
@@ -34,7 +35,7 @@
       String group_id,
       const media::VideoCaptureControlSupport& control_support,
       Vector<media::VideoCaptureFormat> formats,
-      media::VideoFacingMode facing_mode);
+      mojom::blink::FacingMode facing_mode);
   VideoInputDeviceCapabilities();
   VideoInputDeviceCapabilities(VideoInputDeviceCapabilities&& other);
   VideoInputDeviceCapabilities& operator=(VideoInputDeviceCapabilities&& other);
@@ -44,7 +45,7 @@
   String group_id;
   media::VideoCaptureControlSupport control_support;
   Vector<media::VideoCaptureFormat> formats;
-  media::VideoFacingMode facing_mode;
+  mojom::blink::FacingMode facing_mode;
 };
 
 struct MODULES_EXPORT VideoDeviceCaptureCapabilities {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device_test.cc
index 3eabce2..68dd31328 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device_test.cc
@@ -82,7 +82,7 @@
     VideoInputDeviceCapabilities device;
     device.device_id = kDeviceID1;
     device.group_id = kGroupID1;
-    device.facing_mode = media::MEDIA_VIDEO_FACING_NONE;
+    device.facing_mode = mojom::blink::FacingMode::NONE;
     device.formats = {
         media::VideoCaptureFormat(gfx::Size(200, 200), 40.0f,
                                   media::PIXEL_FORMAT_I420),
@@ -100,7 +100,7 @@
     // A low-resolution device.
     device.device_id = kDeviceID2;
     device.group_id = kGroupID2;
-    device.facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
+    device.facing_mode = mojom::blink::FacingMode::ENVIRONMENT;
     device.formats = {
         media::VideoCaptureFormat(gfx::Size(40, 30), 20.0f,
                                   media::PIXEL_FORMAT_I420),
@@ -123,7 +123,7 @@
     // A high-resolution device.
     device.device_id = kDeviceID3;
     device.group_id = kGroupID3;
-    device.facing_mode = media::MEDIA_VIDEO_FACING_USER;
+    device.facing_mode = mojom::blink::FacingMode::USER;
     device.formats = {
         media::VideoCaptureFormat(gfx::Size(600, 400), 10.0f,
                                   media::PIXEL_FORMAT_I420),
@@ -157,7 +157,7 @@
     // A depth capture device.
     device.device_id = kDeviceID4;
     device.group_id = kGroupID4;
-    device.facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
+    device.facing_mode = mojom::blink::FacingMode::ENVIRONMENT;
     device.formats = {media::VideoCaptureFormat(gfx::Size(640, 480), 30.0f,
                                                 media::PIXEL_FORMAT_Y16)};
     device.control_support.pan = true;
@@ -169,7 +169,7 @@
     // be supported if no constraints are placed on the frame rate.
     device.device_id = kDeviceID5;
     device.group_id = kGroupID5;
-    device.facing_mode = media::MEDIA_VIDEO_FACING_NONE;
+    device.facing_mode = mojom::blink::FacingMode::NONE;
     device.formats = {
         media::VideoCaptureFormat(
             gfx::Size(MediaStreamVideoSource::kDefaultWidth,
@@ -405,7 +405,7 @@
   VideoDeviceCaptureCapabilities capabilities;
   VideoInputDeviceCapabilities device;
   device.device_id = kDeviceID1;
-  device.facing_mode = media::MEDIA_VIDEO_FACING_NONE;
+  device.facing_mode = mojom::blink::FacingMode::NONE;
   device.formats = {
       media::VideoCaptureFormat(gfx::Size(200, 200), 40.0f,
                                 media::PIXEL_FORMAT_I420),
@@ -505,7 +505,7 @@
   // Only the low-res device supports environment facing mode. Should select
   // default settings for everything else.
   EXPECT_EQ(low_res_device_->device_id.Utf8(), result.device_id());
-  EXPECT_EQ(media::MEDIA_VIDEO_FACING_ENVIRONMENT,
+  EXPECT_EQ(mojom::blink::FacingMode::ENVIRONMENT,
             low_res_device_->facing_mode);
   EXPECT_EQ(*low_res_closest_format_, result.Format());
   CheckTrackAdapterSettingsEqualsFormat(result);
@@ -516,7 +516,7 @@
   // Only the high-res device supports user facing mode. Should select default
   // settings for everything else.
   EXPECT_EQ(high_res_device_->device_id.Utf8(), result.device_id());
-  EXPECT_EQ(media::MEDIA_VIDEO_FACING_USER, high_res_device_->facing_mode);
+  EXPECT_EQ(mojom::blink::FacingMode::USER, high_res_device_->facing_mode);
   EXPECT_EQ(*high_res_closest_format_, result.Format());
   CheckTrackAdapterSettingsEqualsFormat(result);
 }
@@ -1992,7 +1992,7 @@
   VideoDeviceCaptureCapabilities capabilities;
   VideoInputDeviceCapabilities device;
   device.device_id = kDeviceID1;
-  device.facing_mode = media::MEDIA_VIDEO_FACING_NONE;
+  device.facing_mode = mojom::blink::FacingMode::NONE;
   device.formats = {
       media::VideoCaptureFormat(gfx::Size(200, 200), 40.0f,
                                 media::PIXEL_FORMAT_I420),
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
index 8dc00f69..757d2d8 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -672,7 +672,8 @@
       settings.frame_rate = *computed_frame_rate_;
   }
 
-  settings.facing_mode = ToPlatformFacingMode(source_->device().video_facing);
+  settings.facing_mode = ToPlatformFacingMode(
+      static_cast<mojom::blink::FacingMode>(source_->device().video_facing));
   settings.resize_mode = WebString::FromASCII(std::string(
       adapter_settings().target_size() ? WebMediaStreamTrack::kResizeModeRescale
                                        : WebMediaStreamTrack::kResizeModeNone));
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc b/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
index af4af43b..b947e74 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
@@ -192,7 +192,7 @@
         blink::mojom::blink::VideoInputDeviceCapabilities::New();
     device->device_id = kFakeVideoInputDeviceId1;
     device->group_id = String("dummy");
-    device->facing_mode = media::MEDIA_VIDEO_FACING_USER;
+    device->facing_mode = mojom::blink::FacingMode::USER;
     if (!video_source_ || !video_source_->IsRunning() ||
         !video_source_->GetCurrentFormat()) {
       device->formats.push_back(media::VideoCaptureFormat(
@@ -210,7 +210,7 @@
     device = blink::mojom::blink::VideoInputDeviceCapabilities::New();
     device->device_id = kFakeVideoInputDeviceId2;
     device->group_id = String("dummy");
-    device->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
+    device->facing_mode = mojom::blink::FacingMode::ENVIRONMENT;
     device->formats.push_back(media::VideoCaptureFormat(
         gfx::Size(640, 480), 30.0f, media::PIXEL_FORMAT_I420));
     result.push_back(std::move(device));
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
index dc395ab..f331ca7 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -1277,8 +1277,8 @@
         // operate over WTF::Vector.
         String::FromUTF8(device.id),
         ToStdVector(*current_request_info_->GetNativeVideoFormats(device_id)),
-        device.video_facing, current_request_info_->is_video_device_capture(),
-        device.group_id));
+        static_cast<mojom::blink::FacingMode>(device.video_facing),
+        current_request_info_->is_video_device_capture(), device.group_id));
     local_sources_.push_back(source);
   }
   return source;
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
index baa6b021..e2e228a 100644
--- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
+++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
@@ -11,7 +11,8 @@
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h"
 #include "third_party/blink/renderer/modules/screen_orientation/web_lock_orientation_callback.h"
@@ -289,7 +290,7 @@
   blink::ScreenInfo screen_info;
   screen_info.orientation_angle = 90;
   auto* web_frame_widget_base =
-      static_cast<WebFrameWidgetBase*>(frame->GetWidgetForLocalRoot());
+      static_cast<WebFrameWidgetImpl*>(frame->GetWidgetForLocalRoot());
   web_frame_widget_base->UpdateScreenInfo(screen_info);
   EXPECT_EQ(grandchild_orientation->angle(), 90);
 
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 558ef9f..b1a96ac 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1489,6 +1489,8 @@
     "widget/input/input_event_prediction.cc",
     "widget/input/input_event_prediction.h",
     "widget/input/input_handler_proxy.cc",
+    "widget/input/input_metrics.cc",
+    "widget/input/input_metrics.h",
     "widget/input/main_thread_event_queue.cc",
     "widget/input/main_thread_event_queue.h",
     "widget/input/main_thread_event_queue_task.h",
diff --git a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
index 7236054e..5cd5a3a 100644
--- a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
+++ b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
@@ -69,7 +69,7 @@
 
   // The main thread is given a base::WeakPtr to this class to hand to the
   // PaintWorklet thread(s), so that they can register and unregister
-  // PaintWorklets. See blink::WebFrameWidgetBase for where this happens.
+  // PaintWorklets. See blink::WebFrameWidgetImpl for where this happens.
   base::WeakPtr<PaintWorkletPaintDispatcher> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
diff --git a/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
index 7a0b4fa..d9f2f16 100644
--- a/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium AUthors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this sink code is governed by a BSD-style license that can be found
 // in the LICENSE file.
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 99605cb..cadb603 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1233,6 +1233,10 @@
       status: "experimental",
     },
     {
+      name: "MediaSourceExtensionsForWebCodecs",
+      status: "experimental",
+    },
+    {
       name: "MediaSourceInWorkers",
       status: "experimental",
     },
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
index cf5a4e2b..95f5509 100644
--- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
+++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
@@ -39,6 +39,7 @@
 #include "third_party/blink/renderer/platform/widget/input/cursor_control_handler.h"
 #include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
 #include "third_party/blink/renderer/platform/widget/input/event_with_callback.h"
+#include "third_party/blink/renderer/platform/widget/input/input_metrics.h"
 #include "third_party/blink/renderer/platform/widget/input/momentum_scroll_jank_tracker.h"
 #include "third_party/blink/renderer/platform/widget/input/scroll_predictor.h"
 #include "ui/events/types/scroll_input_type.h"
@@ -791,11 +792,6 @@
 void InputHandlerProxy::RecordMainThreadScrollingReasons(
     WebGestureDevice device,
     uint32_t reasons) {
-  static const char* kGestureHistogramName =
-      "Renderer4.MainThreadGestureScrollReason";
-  static const char* kWheelHistogramName =
-      "Renderer4.MainThreadWheelScrollReason";
-
   if (device != WebGestureDevice::kTouchpad &&
       device != WebGestureDevice::kScrollbar &&
       device != WebGestureDevice::kTouchscreen) {
@@ -842,27 +838,23 @@
   const bool is_unblocked_compositor_scroll =
       reasons == cc::MainThreadScrollingReason::kNotScrollingOnMain;
 
-  // UMA_HISTOGRAM_ENUMERATION requires that the enum_max must be strictly
-  // greater than the sample value. kMainThreadScrollingReasonCount doesn't
-  // include the NotScrollingOnMain enum but the histograms do so adding
-  // the +1 is necessary.
-  // TODO(dcheng): Fix https://crbug.com/705169 so this isn't needed.
-  constexpr uint32_t kMainThreadScrollingReasonEnumMax =
-      cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount + 1;
   if (is_unblocked_compositor_scroll) {
-    if (device == WebGestureDevice::kTouchscreen) {
-      UMA_HISTOGRAM_ENUMERATION(
-          kGestureHistogramName,
-          cc::MainThreadScrollingReason::kNotScrollingOnMain,
-          kMainThreadScrollingReasonEnumMax);
-    } else {
-      UMA_HISTOGRAM_ENUMERATION(
-          kWheelHistogramName,
-          cc::MainThreadScrollingReason::kNotScrollingOnMain,
-          kMainThreadScrollingReasonEnumMax);
-    }
+    RecordScrollReasonMetric(
+        device, cc::MainThreadScrollingReason::kNotScrollingOnMain);
   }
 
+  // The enum in cc::MainThreadScrollingReason simultaneously defines actual
+  // bitmask values and indices into the bitmask, making this loop a bit
+  // confusing.
+  //
+  // This stems from the fact that kNotScrollingOnMain is recorded in the
+  // histograms as value 0. However, the 0th bit is not actually reserved and
+  // has a separate, well-defined meaning. kNotScrollingOnMain is only recorded
+  // when *no* bits are set.
+  //
+  // As such, when recording any reason that's not kNotScrollingOnMain (i.e.
+  // recording the index of a set bit), the index must be incremented by 1 to be
+  // recorded properly.
   for (uint32_t i = 0;
        i < cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount;
        ++i) {
@@ -876,13 +868,7 @@
         if (reasons & ~val)
           continue;
       }
-      if (device == WebGestureDevice::kTouchscreen) {
-        UMA_HISTOGRAM_ENUMERATION(kGestureHistogramName, i + 1,
-                                  kMainThreadScrollingReasonEnumMax);
-      } else {
-        UMA_HISTOGRAM_ENUMERATION(kWheelHistogramName, i + 1,
-                                  kMainThreadScrollingReasonEnumMax);
-      }
+      RecordScrollReasonMetric(device, i + 1);
     }
   }
 }
diff --git a/third_party/blink/renderer/platform/widget/input/input_metrics.cc b/third_party/blink/renderer/platform/widget/input/input_metrics.cc
new file mode 100644
index 0000000..d8313cd9
--- /dev/null
+++ b/third_party/blink/renderer/platform/widget/input/input_metrics.cc
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/widget/input/input_metrics.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "cc/input/main_thread_scrolling_reason.h"
+#include "third_party/blink/public/common/input/web_gesture_device.h"
+
+namespace blink {
+
+void RecordScrollReasonMetric(WebGestureDevice device, uint32_t reason) {
+  constexpr uint32_t kMainThreadScrollingReasonEnumMax =
+      cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount + 1;
+  // Note the use of `UMA_HISTOGRAM_EXACT_LINEAR` here. This is because the enum
+  // defined in cc::MainThreadScrollingReason defines both bitmasks and bitmask
+  // positions and doesn't correspond well to how the UMA helpers for
+  // enumerations are typically used.
+  if (device == WebGestureDevice::kTouchscreen) {
+    UMA_HISTOGRAM_EXACT_LINEAR("Renderer4.MainThreadGestureScrollReason",
+                               reason, kMainThreadScrollingReasonEnumMax);
+  } else {
+    UMA_HISTOGRAM_EXACT_LINEAR("Renderer4.MainThreadWheelScrollReason", reason,
+                               kMainThreadScrollingReasonEnumMax);
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/input/input_metrics.h b/third_party/blink/renderer/platform/widget/input/input_metrics.h
new file mode 100644
index 0000000..f4d64722
--- /dev/null
+++ b/third_party/blink/renderer/platform/widget/input/input_metrics.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_METRICS_H_
+
+#include "cc/input/main_thread_scrolling_reason.h"
+#include "third_party/blink/public/common/input/web_gesture_device.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// `reason` is derived from `cc::MainThreadScrollingReason`. If recording
+// `kNotScrollingOnMain`, simply pass it as-is. Hoewver, if recording the
+// position of a set bit, the index of the set bit must be incremented by one.
+//
+// This stems from the fact that kNotScrollingOnMain is recorded in the
+// histograms as value 0. However, the 0th bit is not actually reserved and
+// has a separate, well-defined meaning. kNotScrollingOnMain is only
+// recorded when *no* bits are set.
+PLATFORM_EXPORT void RecordScrollReasonMetric(WebGestureDevice device,
+                                              uint32_t reason);
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_METRICS_H_
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 67f872df..98c59ed 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -312,34 +312,34 @@
   //    properties are usually the same for every WidgetBase, except when
   //    device emulation changes them in the main frame WidgetBase only.
   //    Example: screen_info.
-  // 3. Computed in the renderer of the main frame WebFrameWidgetBase (in blink
+  // 3. Computed in the renderer of the main frame WebFrameWidgetImpl (in blink
   //    usually). Passed down through the waterfall dance to child frame
-  //    WebFrameWidgetBase. Here that step is performed by passing the value
-  //    along to all RemoteFrame objects that are below this WebFrameWidgetBase
-  //    in the frame tree. The main frame (top level) WebFrameWidgetBase ignores
+  //    WebFrameWidgetImpl. Here that step is performed by passing the value
+  //    along to all RemoteFrame objects that are below this WebFrameWidgetImpl
+  //    in the frame tree. The main frame (top level) WebFrameWidgetImpl ignores
   //    this value from its RenderWidgetHost since it is controlled in the
-  //    renderer. Child frame WebFrameWidgetBases consume the value from their
+  //    renderer. Child frame WebFrameWidgetImpls consume the value from their
   //    RenderWidgetHost. Example: page_scale_factor.
   // 4. Computed independently in the renderer for each WidgetBase (in blink
   //    usually). Passed down from the parent to the child WidgetBases through
   //    the waterfall dance, but the value only travels one step - the child
-  //    frame WebFrameWidgetBase would compute values for grandchild
-  //    WebFrameWidgetBases independently. Here the value is passed to child
+  //    frame WebFrameWidgetImpl would compute values for grandchild
+  //    WebFrameWidgetImpls independently. Here the value is passed to child
   //    frame RenderWidgets by passing the value along to all RemoteFrame
-  //    objects that are below this WebFrameWidgetBase in the frame tree. Each
+  //    objects that are below this WebFrameWidgetImpl in the frame tree. Each
   //    WidgetBase consumes this value when it is received from its
   //    RenderWidgetHost. Example: compositor_viewport_pixel_rect.
   // For each of these properties:
-  //   If the WebView also knows these properties, each WebFrameWidgetBase
+  //   If the WebView also knows these properties, each WebFrameWidgetImpl
   //   will pass them along to the WebView as it receives it, even if there
-  //   are multiple WebFrameWidgetBases related to the same WebView.
+  //   are multiple WebFrameWidgetImpls related to the same WebView.
   //   However when the main frame in the renderer is the source of truth,
   //   then child widgets must not clobber that value! In all cases child frames
   //   do not need to update state in the WebView when a local main frame is
   //   present as it always sets the value first.
   //   TODO(danakj): This does create a race if there are multiple
-  //   UpdateVisualProperties updates flowing through the WebFrameWidgetBase
-  //   tree at the same time, and it seems that only one WebFrameWidgetBase for
+  //   UpdateVisualProperties updates flowing through the WebFrameWidgetImpl
+  //   tree at the same time, and it seems that only one WebFrameWidgetImpl for
   //   each WebView should be responsible for this update.
   //
   //   TODO(danakj): A more explicit API to give values from here to RenderView
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
index b4fe764..fe98889 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -51,7 +51,7 @@
 }
 
 // This class is the foundational class for all widgets that blink creates.
-// (WebPagePopupImpl, WebFrameWidgetBase) will contain an instance of this
+// (WebPagePopupImpl, WebFrameWidgetImpl) will contain an instance of this
 // class. For simplicity purposes this class will be a member of those classes.
 //
 // Co-orindates handled in this class can be in the "blink coordinate space"
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 8c6edaf..d8d0834f 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -657,7 +657,7 @@
     },
     {
         'paths':
-        ['third_party/blink/renderer/core/frame/web_frame_widget_base.cc'],
+        ['third_party/blink/renderer/core/frame/web_frame_widget_impl.cc'],
         'allowed': [
             'cc::InputHandlerScrollResult',
             'cc::SwapPromise',
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index 525599a..ab74220 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -421,6 +421,7 @@
 crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html [ Crash Failure ]
 crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Failure ]
 crbug.com/875235 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-painting-order.html [ Failure ]
+crbug.com/1151295 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2.html [ Failure ]
 
 ### virtual/text-antialias/
 crbug.com/591099 virtual/text-antialias/justify-ideograph-simple.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f0a3143..8d000c9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6029,4 +6029,5 @@
 crbug.com/1149771 [ Linux ] virtual/android/fullscreen/video-scrolled-iframe.html [ Pass Timeout ]
 crbug.com/1152532 http/tests/devtools/service-workers/user-agent-override.js [ Pass Timeout ]
 crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.html [ Pass Timeout ]
-crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.worker.html [ Pass Timeout ]
\ No newline at end of file
+crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.worker.html [ Pass Timeout ]
+crbug.com/1134459 accessibility/aom-click-action.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/external/wpt/cookies/attributes/invalid.html b/third_party/blink/web_tests/external/wpt/cookies/attributes/invalid.html
new file mode 100644
index 0000000..9e723949
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/attributes/invalid.html
@@ -0,0 +1,80 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Test invalid attribute parsing</title>
+    <meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2">
+    <meta name="timeout" content="long">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/cookies/resources/cookie-helper.sub.js"></script>
+  </head>
+  <body>
+    <div id=log></div>
+    <script>
+      // These tests ensure that invalid attributes don't affect
+      // cookie parsing. `Path` isn't important to the tests where it appears,
+      // but it's used to be able to place the invalid attribute in different
+      // locations.
+      const invalidAttributeTests = [
+      {
+        cookie: "test=1; lol; Path=/",
+        expected: "test=1",
+        name: "Set cookie with invalid attribute"
+      },
+      {
+        cookie: "test=2; Path=/; lol",
+        expected: "test=2",
+        name: "Set cookie ending with invalid attribute."
+      },
+      {
+        cookie: "test=3; Path=/; 'lol'",
+        expected: "test=3",
+        name: "Set cookie ending with quoted invalid attribute."
+      },
+      {
+        cookie: 'test=4; Path=/; "lol"',
+        expected: "test=4",
+        name: "Set cookie ending with double-quoted invalid attribute."
+      },
+      {
+        cookie: "test=5; Path=/; lol=",
+        expected: "test=5",
+        name: "Set cookie ending with invalid attribute equals."
+      },
+      {
+        cookie: 'test=6; lol="aaa;bbb"; Path=/',
+        expected: "test=6",
+        name: "Set cookie with two invalid attributes (lol=\"aaa and bbb)."
+      },
+      {
+        cookie: 'test=7; Path=/; lol="aaa;bbb"',
+        expected: "test=7",
+        name: "Set cookie ending with two invalid attributes (lol=\"aaa and bbb)."
+      },
+      {
+        cookie: 'test=8; "Secure"',
+        expected: "test=8",
+        // This gets parsed as an unrecognized \"Secure\" attribute, not a valid
+        // Secure attribute. That's why it gets set on an non-secure origin.
+        name: "Set cookie for quoted Secure attribute",
+        defaultPath: true
+      },
+      {
+        cookie: "test=9; Secure qux",
+        expected: "test=9",
+        // This should be parsed as an unrecognized "Secure qux" attribute
+        // and ignored. That is, the cookie will not be Secure.
+        name: "Set cookie for Secure qux",
+        defaultPath: true
+      },
+    ];
+
+      for (const test of invalidAttributeTests) {
+        promise_test(async testCase => {
+          await runCookieTest(test.cookie, test.expected, test.defaultPath);
+        }, test.name);
+      }
+    </script>
+  </body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/cookies/attributes/path.html b/third_party/blink/web_tests/external/wpt/cookies/attributes/path.html
new file mode 100644
index 0000000..ca8d049
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/attributes/path.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Test cookie path attribute parsing</title>
+    <meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.4">
+    <meta name="timeout" content="long">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/cookies/resources/cookie-helper.sub.js"></script>
+  </head>
+  <body>
+    <script>
+      const pathTests = [
+        {
+          cookie: "test=1; Path",
+          expected: "test=1",
+          name: "Set cookie for bare Path",
+          defaultPath: true
+        },
+        {
+          cookie: "test=2; Path=",
+          expected: "test=2",
+          name: "Set cookie for Path=",
+          defaultPath: true
+        },
+        {
+          cookie: "test=3; Path=/",
+          expected: "test=3",
+          name: "Set cookie for Path=/"
+        },
+        {
+          cookie: "test=4; Path=/qux",
+          expected: "",
+          name: "No cookie returned for mismatched path"
+        },
+        {
+          cookie: "test=5; Path    =/qux",
+          expected: "",
+          name: "No cookie returned for path space equals mismatched path"
+        },
+        {
+          cookie: "test=6; Path=    /qux",
+          expected: "",
+          name: "No cookie returned for path equals space mismatched path"
+        },
+        {
+          cookie: "test=7; Path=/qux      ; taz",
+          expected: "",
+          name: "No cookie returned for mismatched path and attribute"
+        },
+        {
+          cookie: "test=8; Path=/qux; Path=/",
+          expected: "test=8",
+          name: "Set cookie for mismatched and root path"
+        },
+        {
+          cookie: "test=9; Path=/; Path=/qux",
+          expected: "",
+          name: "No cookie returned for root and mismatched path"
+        },
+        {
+          cookie: "test=10; Path=/lol; Path=/qux",
+          expected: "",
+          name: "No cookie returned for multiple mismatched paths"
+        },
+      ];
+
+      for (const test of pathTests) {
+        promise_test(async testCase => {
+          await runCookieTest(test.cookie, test.expected, test.defaultPath);
+        }, test.name);
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/attributes/resources/secure-non-secure-child.html b/third_party/blink/web_tests/external/wpt/cookies/attributes/resources/secure-non-secure-child.html
new file mode 100644
index 0000000..f6a4682
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/attributes/resources/secure-non-secure-child.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Test cookie secure attribute parsing (on non-secure page)</title>
+    <meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.5">
+    <meta name="timeout" content="long">
+    <script src="/resources/testharness.js"></script>
+    <script src="/cookies/resources/cookie-helper.sub.js"></script>
+  </head>
+  <body>
+    <script>
+      // These tests are the non-secure analog to secure.https.html.
+      // They're not in the /cookies/attributes folder because they shouldn't
+      // be run by themselves. Instead, /cookies/attributes/secure.https.html
+      // opens this in a non-secure window.
+      const secureNonSecureTests = [
+      {
+        cookie: "test=1; Secure",
+        expected: "",
+        name: "(non-secure) Ignore cookie for Secure attribute",
+        defaultPath: true
+      },
+      {
+        cookie: "test=2; seCURe",
+        expected: "",
+        name: "(non-secure) Ignore cookie for seCURe attribute",
+        defaultPath: true
+      },
+      {
+        cookie: "test=3; Secure=",
+        expected: "",
+        name: "(non-secure) Ignore cookie for for Secure= attribute",
+        defaultPath: true
+      },
+      {
+        cookie: "test=4; Secure=aaaa",
+        expected: "",
+        name: "(non-secure) Ignore cookie for Secure=aaaa",
+        defaultPath: true
+      },
+      {
+        cookie: "test=5; Secure =aaaaa",
+        expected: "",
+        name: "(non-secure) Ignore cookie for Secure space equals",
+        defaultPath: true
+      },
+      {
+        cookie: "test=6; Secure= aaaaa",
+        expected: "",
+        name: "(non-secure) Ignore cookie for Secure equals space",
+        defaultPath: true
+      },
+      {
+        cookie: "test=7;                Secure",
+        expected: "",
+        name: "(non-secure) Ignore cookie for spaced Secure",
+        defaultPath: true
+      },
+      {
+        cookie: "test=8;       Secure     ;",
+        expected: "",
+        name: "(non-secure) Ignore cookie for space Secure with ;",
+        defaultPath: true
+      }
+    ];
+
+    for (const test of secureNonSecureTests) {
+      promise_test(async testCase => {
+        await runCookieTest(test.cookie, test.expected, test.defaultPath);
+      }, test.name);
+    }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/attributes/secure-non-secure.html b/third_party/blink/web_tests/external/wpt/cookies/attributes/secure-non-secure.html
new file mode 100644
index 0000000..55f11f3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/attributes/secure-non-secure.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Test cookie secure attribute parsing (non-secure origin)</title>
+    <meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.5">
+    <meta name="timeout" content="long">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/cookies/resources/cookie-helper.sub.js"></script>
+  </head>
+  <body>
+    <div id=log></div>
+    <script>
+      test(t => {
+        const win = window.open(`${INSECURE_ORIGIN}/cookies/attributes/resources/secure-non-secure-child.html`);
+        fetch_tests_from_window(win);
+      });
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/attributes/secure.https.html b/third_party/blink/web_tests/external/wpt/cookies/attributes/secure.https.html
new file mode 100644
index 0000000..5e73758c4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/attributes/secure.https.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Test cookie secure attribute parsing</title>
+    <meta name=help href="https://tools.ietf.org/html/rfc6265#section-5.2.5">
+    <meta name="timeout" content="long">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/cookies/resources/cookie-helper.sub.js"></script>
+  </head>
+  <body>
+    <div id=log></div>
+    <script>
+      const secureTests = [
+        {
+          cookie: "test=1; Secure",
+          expected: "test=1",
+          name: "Set cookie for Secure attribute",
+          defaultPath: true
+        },
+        {
+          cookie: "test=2; seCURe",
+          expected: "test=2",
+          name: "Set cookie for seCURe attribute",
+          defaultPath: true
+        },
+        {
+          cookie: "test=3; Secure=",
+          expected: "test=3",
+          name: "Set cookie for for Secure= attribute",
+          defaultPath: true
+        },
+        {
+          cookie: "test=4; Secure=aaaa",
+          expected: "test=4",
+          name: "Set cookie for Secure=aaaa",
+          defaultPath: true
+        },
+        {
+          cookie: "test=5; Secure =aaaaa",
+          expected: "test=5",
+          name: "Set cookie for Secure space equals",
+          defaultPath: true
+        },
+        {
+          cookie: "test=6; Secure= aaaaa",
+          expected: "test=6",
+          name: "Set cookie for Secure equals space",
+          defaultPath: true
+        },
+        {
+          cookie: "test=7;                Secure",
+          expected: "test=7",
+          name: "Set cookie for spaced Secure",
+          defaultPath: true
+        },
+        {
+          cookie: "test=8;       Secure     ;",
+          expected: "test=8",
+          name: "Set cookie for space Secure with ;",
+          defaultPath: true
+        }
+      ];
+
+      for (const test of secureTests) {
+        promise_test(async testCase => {
+          await runCookieTest(test.cookie, test.expected, test.defaultPath);
+        }, test.name);
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/attribute-tests.html b/third_party/blink/web_tests/external/wpt/cookies/http-state/attribute-tests.html
deleted file mode 100644
index 5d93300..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/attribute-tests.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <meta charset=utf-8>
-    <title>Tests cookie attribute functionality</title>
-    <meta name=help href="https://tools.ietf.org/html/rfc6265#page-8">
-    <meta name="timeout" content="long">
-
-    <script src="/resources/testharness.js"></script>
-    <script src="/resources/testharnessreport.js"></script>
-    <script src="resources/cookie-http-state-template.js"></script>
-  </head>
-  <body>
-    <div id="log"></div>
-    <div id="iframes"></div>
-    <script>
-      setup({ explicit_timeout: true });
-
-      const TEST_CASES = [
-        {file: "attribute0001", name: "Ignore cookie for Secure attribute."},
-        {file: "attribute0002", name: "Ignore cookie for seCURe attribute."},
-        {file: "attribute0003", name: "Set cookie for \"Secure\" attribute."},
-        {file: "attribute0004", name: "Ignore cookie for for Secure= attribute."},
-        {file: "attribute0005", name: "Ignore cookie for Secure=aaaa"},
-        {file: "attribute0006", name: "Set cookie for Secure qux"},
-        {file: "attribute0007", name: "Ignore cookie for Secure space equals."},
-        {file: "attribute0008", name: "Ignore cookie for Secure equals space"},
-        {file: "attribute0009", name: "Ignore cookie for Secure separated."},
-        {file: "attribute0010", name: "Ignore cookie for Secure separated v2."},
-        {file: "attribute0011", name: "Ignore cookie for Secure separated v2."},
-        {file: "attribute0012", name: "Ignore cookie for spaced Secure"},
-        {file: "attribute0013", name: "Ignore cookie for space Secure with ;."},
-        {file: "attribute0014", name: "Set cookie for Path."},
-        {file: "attribute0015", name: "Set cookie for Path=."},
-        {file: "attribute0016", name: "Set cookie for Path=/."},
-        {file: "attribute0017", name: "Ignore cookie for invalid path."},
-        {file: "attribute0018", name: "Ignore cookie for spaced invalid path."},
-        {file: "attribute0019", name: "Ignore cookie for spaced invalid path v2."},
-        {file: "attribute0020", name: "Ignore cookie for invalid path and attribute."},
-        {file: "attribute0021", name: "Ignore cookie for invalid and root path."},
-        {file: "attribute0022", name: "Set cookie for root and invalid path."},
-        {file: "attribute0023", name: "Set cookie for invalid and sane path."},
-        {file: "attribute0024", name: "Ignore cookie for sane and invalid path."},
-        {file: "attribute0025", name: "Ignore cookie for invalid + Secure."},
-        {file: "attribute0026", name: "Ignore cookie for quoted invalid attribute."},
-      ];
-
-      for (const i in TEST_CASES) {
-        const t = TEST_CASES[i];
-        promise_test(createCookieTest(t.file),
-                     t.file + " - " + t.name);
-      }
-
-    </script>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-test
deleted file mode 100644
index 6199f78c..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0001-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-test
deleted file mode 100644
index 047a24d9..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0002-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; seCURe
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-test
deleted file mode 100644
index c944bac..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0003-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; "Secure"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-test
deleted file mode 100644
index bcfaa7d..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0004-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure=
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-test
deleted file mode 100644
index 16710878..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0005-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure=aaaa
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-test
deleted file mode 100644
index 39d7589..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0006-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-test
deleted file mode 100644
index f75f46a7..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0007-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure =aaaaa
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-test
deleted file mode 100644
index be45b3a2..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0008-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure= aaaaa
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-test
deleted file mode 100644
index 1a44c22..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0009-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure; qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-test
deleted file mode 100644
index ca62200..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0010-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure;qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-test
deleted file mode 100644
index 3bd4c2e..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0011-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Secure    ; qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-test
deleted file mode 100644
index 6e7b816..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0012-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar;                Secure
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-test
deleted file mode 100644
index f4814e4..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0013-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar;       Secure     ;
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-test
deleted file mode 100644
index ef88896a..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0014-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-test
deleted file mode 100644
index cea7060a..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0015-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-test
deleted file mode 100644
index 9a5b591a..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0016-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-test
deleted file mode 100644
index a6aeeb3..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0017-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-test
deleted file mode 100644
index f91220134..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0018-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path    =/qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-test
deleted file mode 100644
index a424c6e..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0019-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=    /qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-test
deleted file mode 100644
index 367d2a10..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0020-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/qux      ; taz
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-expected
deleted file mode 100644
index b14d4f69..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-expected
+++ /dev/null
@@ -1 +0,0 @@
-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-test
deleted file mode 100644
index bb76deb..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0021-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/qux; Path=/
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-test
deleted file mode 100644
index ac79c0f9..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0022-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/; Path=/qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-test
deleted file mode 100644
index 97f2ac3..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0023-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/qux; Path=/cookie-parser-result
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-test
deleted file mode 100644
index cb041c56..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0024-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; Path=/cookie-parser-result; Path=/qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-test
deleted file mode 100644
index c4309435..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0025-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; qux; Secure
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-expected
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-expected
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-test
deleted file mode 100644
index 7f68322e..0000000
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/attribute0026-test
+++ /dev/null
@@ -1 +0,0 @@
-Set-Cookie: foo=bar; qux="aaa;bbb"; Secure
diff --git a/third_party/blink/web_tests/external/wpt/cookies/resources/cookie-helper.sub.js b/third_party/blink/web_tests/external/wpt/cookies/resources/cookie-helper.sub.js
index 50dcdfc..3f0aac26 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/resources/cookie-helper.sub.js
+++ b/third_party/blink/web_tests/external/wpt/cookies/resources/cookie-helper.sub.js
@@ -309,3 +309,52 @@
   var re = new RegExp("(?:^|; )" + name);
   assert_equals(re.test(document.cookie), false, "Sanity check: " + name + " has been deleted.");
 }
+
+// getDefaultPathCookies is a helper method to get and delete cookies on the
+// "default path" (which for these tests will be at `/cookies/resources`),
+// determined by the path portion of the request-uri.
+async function getDefaultPathCookies(path = '/cookies/resources') {
+  return new Promise((resolve, reject) => {
+    try {
+      const iframe = document.createElement('iframe');
+      iframe.style = 'display: none';
+      iframe.src = `${path}/echo-cookie.html`;
+
+      iframe.addEventListener('load', (e) => {
+        const win = e.target.contentWindow;
+        const iframeCookies = win.getCookies();
+        win.expireCookie('test', path);
+        resolve(iframeCookies);
+      }, {once: true});
+
+      document.documentElement.appendChild(iframe);
+    } catch (e) {
+      reject(e);
+    }
+  });
+}
+
+// runCookieTest sets a |cookie|, then asserts it was or was not set
+// via |expectedValue|. Then cleans it up.
+async function runCookieTest(cookie, expectedValue, defaultPath) {
+  return fetch(`/cookies/resources/cookie.py?set=${encodeURIComponent(cookie)}`)
+      .then(async _ => {
+        let cookies = document.cookie;
+        // for the tests where a Path is set from the request-uri path, we need
+        // to go look for cookies in an iframe at that default path.
+        if (defaultPath) {
+          cookies = await getDefaultPathCookies();
+        }
+
+        if (Boolean(expectedValue)) {
+          assert_equals(
+              cookies, expectedValue, 'The cookie was set as expected.');
+        } else {
+          assert_equals(cookies, expectedValue, 'The cookie was rejected.');
+        }
+      })
+      .then(_ => {
+        return fetch(
+            `/cookies/resources/cookie.py?drop=${encodeURIComponent(cookie)}`);
+      });
+}
diff --git a/third_party/blink/web_tests/external/wpt/cookies/resources/cookie.py b/third_party/blink/web_tests/external/wpt/cookies/resources/cookie.py
new file mode 100644
index 0000000..9710b51
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/cookies/resources/cookie.py
@@ -0,0 +1,33 @@
+from cookies.resources.helpers import setNoCacheAndCORSHeaders
+from wptserve.utils import isomorphic_encode
+
+def main(request, response):
+    """Set or drop a cookie via GET params.
+
+    Usage: `/cookie.py?set={cookie}` or `/cookie.py?drop={cookie}`
+
+    The passed-in cookie string should be encoded via encodeURIComponent,
+    otherwise `parse_qsl` will split on any semicolons (used by the Request.GET
+    property getter).
+
+    Note: here we don't use Response.delete_cookie() or similar other methods
+    in this resources directory because there are edge cases that are impossible
+    to express via those APIs, namely a bare (`Path`) or empty Path (`Path=`)
+    attribute. Instead, we pipe through the entire cookie and append `max-age=0`
+    to it.
+    """
+    headers = setNoCacheAndCORSHeaders(request, response)
+
+    try:
+        if b'drop' in request.GET:
+            cookie = request.GET[b'drop']
+            cookie += "; max-age=0"
+
+        if b'set' in request.GET:
+            cookie = request.GET[b'set']
+
+        headers.append((b'Set-Cookie', isomorphic_encode(cookie)))
+        return headers, b'{"success": true}'
+    except Exception as e:
+          return 500, headers, bytes({'error': '{}'.format(e)})
+
diff --git a/third_party/blink/web_tests/external/wpt/cookies/resources/echo-cookie.html b/third_party/blink/web_tests/external/wpt/cookies/resources/echo-cookie.html
index a715b8b..4780447e 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/resources/echo-cookie.html
+++ b/third_party/blink/web_tests/external/wpt/cookies/resources/echo-cookie.html
@@ -19,6 +19,7 @@
 window.expireCookie = function (name, path) {
   document.cookie = name + '=0; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=' + path + ';';
 };
+window.getCookies = () => document.cookie;
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2-ref.html
new file mode 100644
index 0000000..da2dd3e1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Reference for legend position: relative</title>
+<style>
+#fieldset2 {
+  background: lime;
+  border: 2px solid lime;
+  width: 200px;
+  padding: 0;
+  margin: 0;
+}
+#legend2 {
+  background: #00ffff;
+}
+</style>
+<p>"Legend" should be shown.</p>
+<fieldset id="fieldset2"><legend id="legend2">Legend</legend></fieldset>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2.html
new file mode 100644
index 0000000..3fbdbd5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-position-relative-2.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>legend position: relative</title>
+<link ref=help href="http://crbug.com/1151295">
+<link rel=match href=legend-position-relative-2-ref.html>
+<style>
+#fieldset2 {
+  background: lime;
+  border: 2px solid lime;
+  width: 200px;
+  padding: 0;
+  margin: 0;
+  overflow: hidden;
+}
+#legend2 {
+  position: relative;
+  overflow: hidden;
+  background: #00ffff;
+}
+</style>
+<p>"Legend" should be shown.</p>
+<fieldset id="fieldset2"><legend id="legend2">Legend</legend></fieldset>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-offscreen.html b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-offscreen.html
new file mode 100644
index 0000000..8356a34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-offscreen.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Layout Instability: off-screen content-visibility:auto content</title>
+<link rel="help" href="https://wicg.github.io/layout-instability/" />
+<style>
+  #target {
+    content-visibility: auto;
+    contain-intrinsic-size: 1px;
+    width: 100px;
+  }
+</style>
+<div id=target style="position: relative; top: 100000px">
+  <div style="width: 100px; height: 100px"></div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/util.js"></script>
+<script>
+promise_test(async () => {
+  const watcher = new ScoreWatcher;
+
+  // Wait for the initial render to complete.
+  await waitForAnimationFrames(2);
+
+  window.scrollTo(0, 100000);
+  await waitForAnimationFrames(2);
+
+  assert_equals(watcher.score, 0);
+}, 'off-screen content-visibility:auto');
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-onscreen.html b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-onscreen.html
new file mode 100644
index 0000000..4d9d06a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-auto-onscreen.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Layout Instability: on-screen content-visibility:auto content</title>
+<link rel="help" href="https://wicg.github.io/layout-instability/" />
+<style>
+  #target {
+    content-visibility: auto;
+    contain-intrinsic-size: 1px;
+    width: 100px;
+  }
+</style>
+<div id=target>
+  <div style="width: 100px; height: 100px"></div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/util.js"></script>
+<script>
+promise_test(async () => {
+  const watcher = new ScoreWatcher;
+
+  // Wait for the initial render to complete.
+  await waitForAnimationFrames(2);
+  assert_equals(watcher.score, 0);
+}, 'on-screen content-visibility:auto');
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-hidden.html b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-hidden.html
new file mode 100644
index 0000000..939b1a21
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/layout-instability/content-visibility-hidden.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Layout Instability: content-visibility:hidden content</title>
+<link rel="help" href="https://wicg.github.io/layout-instability/" />
+<style>
+  #target {
+    content-visibility: hidden;
+    contain-intrinsic-size: 1px;
+    width: 100px;
+  }
+</style>
+<div id=target>
+  <div style="width: 100px; height: 100px"></div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/util.js"></script>
+<script>
+promise_test(async () => {
+  const watcher = new ScoreWatcher;
+
+  // Wait for the initial render to complete.
+  await waitForAnimationFrames(2);
+  assert_equals(watcher.score, 0);
+}, 'on-screen content-visibility:auto');
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/README.md b/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
index 4032edf..0987e90 100644
--- a/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
+++ b/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
@@ -19,4 +19,5 @@
 To install them, run:
 ```
 go get -u github.com/WICG/webpackage/go/signedexchange/cmd/...
+export PATH=$PATH:$(go env GOPATH)/bin
 ```
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh b/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
index e3988ce6..9738f7c 100755
--- a/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
+++ b/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
@@ -19,6 +19,7 @@
     if ! command -v $cmd > /dev/null 2>&1; then
         echo "$cmd is not installed. Please run:"
         echo "  go get -u github.com/WICG/webpackage/go/signedexchange/cmd/..."
+        echo '  export PATH=$PATH:$(go env GOPATH)/bin'
         exit 1
     fi
 done
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
index 03b42ab..90c13069 100644
--- a/third_party/blink/web_tests/external/wpt/web-bundle/README.md
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/README.md
@@ -6,4 +6,5 @@
 To install them, run:
 ```
 go get -u github.com/WICG/webpackage/go/bundle/cmd/...
+export PATH=$PATH:$(go env GOPATH)/bin
 ```
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
index 64a54bc..7100e6a 100755
--- 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
@@ -5,6 +5,7 @@
 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/..."
+    echo '  export PATH=$PATH:$(go env GOPATH)/bin'
     exit 1
 fi
 
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001-1.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001-1.html
index 75d689e..c6ef23018 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001-1.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001-1.html
@@ -1,8 +1,6 @@
 <!doctype html>
 <title>WebSockets: navigating top-level browsing context</title>
 <script src=../constants.js?pipe=sub></script>
-<meta name="variant" content="">
-<meta name="variant" content="?wss">
 <script>
 var controller = opener || parent;
 var t = controller.t;
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001.html
index 56e883c..52427b5 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/001.html
@@ -14,7 +14,7 @@
 var uuid;
 t.step(function() {
   uuid = token()
-  w = window.open("001-1.html");
+  w = window.open("001-1.html" + location.search);
   add_result_callback(function() {
     w.close();
   });
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002-1.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002-1.html
index 546de89..04623ff 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002-1.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002-1.html
@@ -1,8 +1,6 @@
 <!doctype html>
 <title>WebSockets: navigating top-level browsing context with closed websocket</title>
 <script src=../constants.js?pipe=sub></script>
-<meta name="variant" content="">
-<meta name="variant" content="?wss">
 <script>
 var controller = opener || parent;
 var t = controller.t;
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html
index 94028e7..748da64 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html
@@ -15,7 +15,7 @@
 var uuid;
 t.step(function() {
   uuid = token()
-  w = window.open("002-1.html");
+  w = window.open("002-1.html" + location.search);
   add_result_callback(function() {
     w.close();
   });
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005-1.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005-1.html
index fd70fc5b..1dbcef22 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005-1.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005-1.html
@@ -1,8 +1,6 @@
 <!doctype html>
 <title>WebSockets: navigating nested browsing context with a websocket in top-level</title>
 <script src=../constants.js?pipe=sub></script>
-<meta name="variant" content="">
-<meta name="variant" content="?wss">
 <script>
 var t = opener.t;
 var assert_unreached = opener.assert_unreached;
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005.html b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005.html
index 81a05f4..588fd76 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005.html
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/005.html
@@ -12,7 +12,7 @@
 <script>
 var t = async_test();
 t.step(function() {
-  var w = window.open("005-1.html");
+  var w = window.open("005-1.html" + location.search);
   add_result_callback(function() {
     w.close();
   });
diff --git a/third_party/blink/web_tests/http/tests/loading/sxg/resources/README.md b/third_party/blink/web_tests/http/tests/loading/sxg/resources/README.md
index 6f71052..e83c19bb 100644
--- a/third_party/blink/web_tests/http/tests/loading/sxg/resources/README.md
+++ b/third_party/blink/web_tests/http/tests/loading/sxg/resources/README.md
@@ -6,6 +6,7 @@
 [webpackage repository][1]. To install them, run:
 ```
 go get -u github.com/WICG/webpackage/go/signedexchange/cmd/...
+export PATH=$PATH:$(go env GOPATH)/bin
 ```
 The revision of the tools used to generate the test files is `cf19833`.
 
diff --git a/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh b/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
index 403b1c16..e27a6e5 100755
--- a/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
+++ b/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
@@ -9,6 +9,7 @@
 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/..."
+    echo '  export PATH=$PATH:$(go env GOPATH)/bin'
     exit 1
 fi
 
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 2b93f585..dc79165 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1415,6 +1415,7 @@
 [Worker]     getter videoTracks
 [Worker]     method abort
 [Worker]     method appendBuffer
+[Worker]     method appendEncodedChunks
 [Worker]     method changeType
 [Worker]     method constructor
 [Worker]     method remove
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 0df2bdc..112ba8ea 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8092,6 +8092,7 @@
     getter videoTracks
     method abort
     method appendBuffer
+    method appendEncodedChunks
     method changeType
     method constructor
     method remove
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index 1913a9d..5d6e922 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -181,9 +181,8 @@
   MESSAGE_SENT: 'message_sent',
   FAILED: 'failed',
   EMPTY: 'empty',
-  FAILED_PLUGIN_VM_TASK_DIRECTORY_NOT_SHARED:
-      'failed_plugin_vm_task_directory_not_shared',
-  FAILED_PLUGIN_VM_TASK_EXTERNAL_DRIVE: 'failed_plugin_vm_task_external_drive',
+  FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED:
+      'failed_plugin_vm_directory_not_shared',
 };
 
 /** @enum {string} */
@@ -268,6 +267,8 @@
   DISABLE: 'disable',
   SHARE: 'share',
   UNSHARE: 'unshare',
+  DROP_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED:
+      'drop_failed_plugin_vm_directory_not_shared',
 };
 
 /**
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index be53a6fa..7da0c81 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -657,6 +657,8 @@
       'mac-updater-builder-rel': 'updater_release_bot',
       'win-updater-builder-dbg': 'updater_debug_bot',
       'win-updater-builder-rel': 'updater_release_bot',
+      'win32-updater-builder-dbg': 'updater_debug_bot_x86',
+      'win32-updater-builder-rel': 'updater_release_bot_x86',
     },
 
     # TODO(crbug.com/818301): This master is going away.
@@ -2332,10 +2334,18 @@
       'updater_on_win_mac', 'debug_bot',
     ],
 
+    'updater_debug_bot_x86': [
+      'updater_on_win_mac', 'debug_bot', 'x86',
+    ],
+
     'updater_release_bot': [
       'updater_on_win_mac', 'release_bot',
     ],
 
+    'updater_release_bot_x86': [
+      'updater_on_win_mac', 'release_bot', 'x86',
+    ],
+
     'updater_release_trybot': [
       'updater_on_win_mac', 'release_trybot',
     ],
diff --git a/tools/mb/mb_config_expectations/chromium.updater.json b/tools/mb/mb_config_expectations/chromium.updater.json
index 37e0053..2b7c3fa 100644
--- a/tools/mb/mb_config_expectations/chromium.updater.json
+++ b/tools/mb/mb_config_expectations/chromium.updater.json
@@ -32,5 +32,24 @@
       "is_google_branded": true,
       "use_goma": true
     }
+  },
+  "win32-updater-builder-dbg": {
+    "gn_args": {
+      "is_component_build": true,
+      "is_debug": true,
+      "is_google_branded": true,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "use_goma": true
+    }
+  },
+  "win32-updater-builder-rel": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "is_google_branded": true,
+      "target_cpu": "x86",
+      "use_goma": true
+    }
   }
 }
\ No newline at end of file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 225190a9..ba23f93 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10026,6 +10026,7 @@
   <summary>Defines Chrome OS sharesheet actions.</summary>
   <int value="0" label="Cancelled by user"/>
   <int value="1" label="Launch ARC app"/>
+  <int value="2" label="Launch share action"/>
 </enum>
 
 <enum name="ChromeOSUICommands">
@@ -22608,6 +22609,7 @@
   <int value="805" label="NTPCardsVisible"/>
   <int value="806" label="BasicAuthOverHttpEnabled"/>
   <int value="807" label="SystemFeaturesDisableMode"/>
+  <int value="808" label="IntegratedWebAuthenticationAllowed"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -30345,6 +30347,9 @@
   <int value="3730" label="AddEventListenerWithAbortSignal"/>
   <int value="3731" label="XRSessionRequestLightProbe"/>
   <int value="3732" label="BeforematchRevealedHiddenMatchable"/>
+  <int value="3733" label="AddSourceBufferUsingConfig"/>
+  <int value="3734" label="ChangeTypeUsingConfig"/>
+  <int value="3735" label="V8SourceBuffer_AppendEncodedChunks_Method"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml
index 5997a7c..0add7a6 100644
--- a/tools/metrics/histograms/histograms_xml/input/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -454,6 +454,16 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.NextWordPrediction" enum="BooleanEnabled"
+    expires_after="2021-04-01">
+  <owner>myy@chromium.org</owner>
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>
+    Whether next word prediction is enabled for a user. Recorded when a specific
+    language settings page is updated or when the input extension is activated.
+  </summary>
+</histogram>
+
 <histogram name="InputMethod.PkCommit.Index" units="units"
     expires_after="2021-04-01">
   <owner>shend@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/sync/histograms.xml b/tools/metrics/histograms/histograms_xml/sync/histograms.xml
index 11b9bad..8483493 100644
--- a/tools/metrics/histograms/histograms_xml/sync/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/sync/histograms.xml
@@ -436,6 +436,17 @@
   </summary>
 </histogram>
 
+<histogram name="Sync.Local.ReadPlatformFileError" enum="PlatformFileError"
+    expires_after="2021-05-31">
+  <owner>pastarmovj@chromium.org</owner>
+  <owner>igorruvinov@chromium.org</owner>
+  <summary>
+    Error code describing failure to read persisted sync state from local file.
+    Recorded when an error is encountered during opening or reading of the local
+    sync state file.
+  </summary>
+</histogram>
+
 <histogram name="Sync.Local.RequestTypeOnError" enum="SyncRequestType"
     expires_after="2021-05-31">
   <owner>pastarmovj@chromium.org</owner>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 8a1f95c05..c4db62e3 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -60,7 +60,7 @@
 system_health.memory_mobile,"pasko@chromium.org, lizeb@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy"
 system_health.weblayer_startup,"cduvall@chromium.org, weblayer-team@chromium.org",Internals>WebLayer,https://bit.ly/36XBtpn,2016
 system_health.webview_startup,"oksamyt@chromium.org, torne@chromium.org, changwan@chromium.org",Mobile>WebView>Perf,,2016
-tab_search,"yuhengh@chromium.org, tluk@chromium.org, romanarora@chromium.org",UI>Browser>TabSearch,,
+tab_search,"yuhengh@chromium.org, tluk@chromium.org, romanarora@chromium.org",UI>Browser>TabSearch,https://chromium.googlesource.com/chromium/src/+/master/docs/speed/benchmark/harnesses/tab_search.md,
 tab_switching.typical_25,vovoy@chromium.org,OS>Performance,,"2016,tabs_switching"
 tracing.tracing_with_background_memory_infra,ssid@chromium.org,,,
 tracing_perftests,"eseckler@chromium.org, oysteine@chromium.org",Speed>Tracing,,
diff --git a/tools/perf/benchmarks/tab_search.py b/tools/perf/benchmarks/tab_search.py
index 8ae4aef..3f1c782 100644
--- a/tools/perf/benchmarks/tab_search.py
+++ b/tools/perf/benchmarks/tab_search.py
@@ -29,10 +29,14 @@
 ]
 
 
-@benchmark.Info(emails=[
-    'yuhengh@chromium.org', 'tluk@chromium.org', 'romanarora@chromium.org'
-],
-                component='UI>Browser>TabSearch')
+@benchmark.Info(
+    emails=[
+        'yuhengh@chromium.org', 'tluk@chromium.org', 'romanarora@chromium.org'
+    ],
+    component='UI>Browser>TabSearch',
+    documentation_url=
+    'https://chromium.googlesource.com/chromium/src/+/master/docs/speed/benchmark/harnesses/tab_search.md'
+)
 class TabSearch(perf_benchmark.PerfBenchmark):
   """Tab Search Benchmark."""
   PLATFORM = 'desktop'
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index ce9909c..8166fba 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -446,6 +446,8 @@
     _GetBenchmarkConfig('rendering.desktop'),
     _GetBenchmarkConfig('system_health.common_desktop')
 ])
+_FUCHSIA_PERF_FYI_BENCHMARK_CONFIGS = PerfSuite(
+    [_GetBenchmarkConfig('system_health.memory_desktop')])
 
 
 # Linux
@@ -563,6 +565,12 @@
                               1,
                               'linux',
                               is_fyi=True)
+FUCHSIA_PERF_FYI = PerfPlatform('fuchsia-perf-fyi',
+                                '',
+                                _FUCHSIA_PERF_FYI_BENCHMARK_CONFIGS,
+                                1,
+                                'fuchsia',
+                                is_fyi=True)
 
 ALL_PLATFORMS = {
     p for p in locals().values() if isinstance(p, PerfPlatform)
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 8b2bd45..cbc4ca5 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -196,6 +196,23 @@
             'pool': 'chrome.tests.perf-fyi',
         },
     },
+    'fuchsia-perf-fyi': {
+        'tests': [{
+            'isolate':
+            'performance_test_suite',
+            'extra_args': [
+                '--output-format=histograms',
+                '--experimental-tbmv3-metrics',
+            ],
+        }],
+        'platform':
+        'fuchsia',
+        'dimension': {
+            'device_type': 'Astro',
+            'os': 'Fuchsia',
+            'pool': 'chrome.tests',
+        },
+    },
     'win-10_laptop_low_end-perf_HP-Candidate': {
         'tests': [
             {
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py
index 31e9924..2e215f0 100644
--- a/tools/perf/core/perf_json_config_validator.py
+++ b/tools/perf/core/perf_json_config_validator.py
@@ -27,6 +27,7 @@
     'android-pixel4a_power-perf': {'chrome.tests.pinpoint'},
     'chromeos-kevin-perf-fyi': {'chrome.tests'},
     'chromeos-amd64-generic-lacros-builder-perf': {'chrome.tests'},
+    'fuchsia-perf-fyi': {'chrome.tests'},
 }
 
 
diff --git a/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json b/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json
new file mode 100644
index 0000000..2c5399a
--- /dev/null
+++ b/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json
@@ -0,0 +1,17 @@
+{
+    "0": {
+        "benchmarks": {
+            "system_health.memory_desktop": {
+                "abridged": false
+            }
+        }
+    },
+    "extra_infos": {
+        "num_stories": 79,
+        "predicted_min_shard_time": 790,
+        "predicted_min_shard_index": 0,
+        "predicted_max_shard_time": 790,
+        "predicted_max_shard_index": 0,
+        "shard #0": 790
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/tools/perf/core/undocumented_benchmarks.py b/tools/perf/core/undocumented_benchmarks.py
index 841e7acf..d108891 100644
--- a/tools/perf/core/undocumented_benchmarks.py
+++ b/tools/perf/core/undocumented_benchmarks.py
@@ -24,7 +24,6 @@
     'speedometer2-future',
     'startup.mobile',
     'system_health.webview_startup',
-    'tab_search',
     'tab_switching.typical_25',
     'tracing.tracing_with_background_memory_infra',
     'tracing_perftests',
diff --git a/tools/vscode/settings.json5 b/tools/vscode/settings.json5
index 30de30da..67e1b97f 100644
--- a/tools/vscode/settings.json5
+++ b/tools/vscode/settings.json5
@@ -24,6 +24,8 @@
     "*.grd" : "xml",
     // Optional: .gn and .gni are not JavaScript, but at least it gives some
     // approximate syntax highlighting. Ignore the linter warnings!
+    // There's an extension for these files, excluding the linter headaches.
+    // https://marketplace.visualstudio.com/items?itemName=npclaudiu.vscode-gn
     "*.gni" : "javascript",
     "*.gn" : "javascript"
   },
diff --git a/ui/events/event.cc b/ui/events/event.cc
index 58b71ae6..a82bc9e9 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -320,13 +320,7 @@
     : type_(type),
       time_stamp_(time_stamp.is_null() ? EventTimeForNow() : time_stamp),
       flags_(flags),
-      native_event_(PlatformEvent()),
-      delete_native_event_(false),
-      cancelable_(true),
-      target_(nullptr),
-      phase_(EP_PREDISPATCH),
-      result_(ER_UNHANDLED),
-      source_device_id_(ED_UNKNOWN_DEVICE) {
+      native_event_(PlatformEvent()) {
   if (type_ < ET_LAST)
     latency()->set_source_event_type(EventTypeToLatencySourceEventType(type));
 }
@@ -335,13 +329,7 @@
     : type_(type),
       time_stamp_(EventTimeFromNative(native_event)),
       flags_(flags),
-      native_event_(native_event),
-      delete_native_event_(false),
-      cancelable_(true),
-      target_(nullptr),
-      phase_(EP_PREDISPATCH),
-      result_(ER_UNHANDLED),
-      source_device_id_(ED_UNKNOWN_DEVICE) {
+      native_event_(native_event) {
   if (type_ < ET_LAST)
     latency()->set_source_event_type(EventTypeToLatencySourceEventType(type));
   ComputeEventLatencyOS(native_event);
@@ -362,10 +350,6 @@
       flags_(copy.flags_),
       native_event_(CopyNativeEvent(copy.native_event_)),
       delete_native_event_(true),
-      cancelable_(true),
-      target_(nullptr),
-      phase_(EP_PREDISPATCH),
-      result_(ER_UNHANDLED),
       source_device_id_(copy.source_device_id_),
       properties_(copy.properties_
                       ? std::make_unique<Properties>(*copy.properties_)
@@ -724,8 +708,6 @@
 TouchEvent::TouchEvent(const PlatformEvent& native_event)
     : LocatedEvent(native_event),
       unique_event_id_(ui::GetNextTouchEventId()),
-      may_cause_scrolling_(false),
-      hovering_(false),
       pointer_details_(GetTouchPointerDetailsFromNative(native_event)) {
   latency()->AddLatencyNumberWithTimestamp(
       INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp());
@@ -740,8 +722,6 @@
                        int flags)
     : LocatedEvent(type, location, root_location, time_stamp, flags),
       unique_event_id_(ui::GetNextTouchEventId()),
-      may_cause_scrolling_(false),
-      hovering_(false),
       pointer_details_(pointer_details) {
   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT);
 }
diff --git a/ui/events/event.h b/ui/events/event.h
index 4224c1b..a1fc79a9 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -312,15 +312,15 @@
   LatencyInfo latency_;
   int flags_;
   PlatformEvent native_event_;
-  bool delete_native_event_;
-  bool cancelable_;
-  EventTarget* target_;
-  EventPhase phase_;
-  EventResult result_;
+  bool delete_native_event_ = false;
+  bool cancelable_ = true;
+  EventTarget* target_ = nullptr;
+  EventPhase phase_ = EP_PREDISPATCH;
+  EventResult result_ = ER_UNHANDLED;
 
   // The device id the event came from, or ED_UNKNOWN_DEVICE if the information
   // is not available.
-  int source_device_id_;
+  int source_device_id_ = ED_UNKNOWN_DEVICE;
 
   std::unique_ptr<Properties> properties_;
 };
@@ -703,11 +703,11 @@
   // Whether the (unhandled) touch event will produce a scroll event (e.g., a
   // touchmove that exceeds the platform slop region, or a touchend that
   // causes a fling). Defaults to false.
-  bool may_cause_scrolling_;
+  bool may_cause_scrolling_ = false;
 
   // True for devices like some pens when they support hovering over
   // digitizer and they send events while hovering.
-  bool hovering_;
+  bool hovering_ = false;
 
   // Structure for holding pointer details for implementing PointerEvents API.
   PointerDetails pointer_details_;
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
index 0f155e1e..339e115f 100644
--- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -55,6 +55,8 @@
   is_polymer3 = true
   deps = [
     ":files_icon_button.m",
+    ":files_metadata_box.m",
+    ":files_metadata_entry.m",
     ":files_ripple.m",
     ":files_toggle_ripple.m",
   ]
@@ -125,9 +127,39 @@
   externs_list = [ "$externs_path/pending_polymer.js" ]
 }
 
+polymer_modulizer("files_metadata_box") {
+  js_file = "files_metadata_box.js"
+  html_file = "files_metadata_box.html"
+  html_type = "dom-module"
+  preserve_url_scheme = true
+}
+
+js_library("files_metadata_box.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/elements/files_metadata_box.m.js" ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  extra_deps = [ ":files_metadata_box_module" ]
+}
+
 js_library("files_metadata_entry") {
 }
 
+polymer_modulizer("files_metadata_entry") {
+  js_file = "files_metadata_entry.js"
+  html_file = "files_metadata_entry.html"
+  html_type = "dom-module"
+  preserve_url_scheme = true
+}
+
+js_library("files_metadata_entry.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.m.js" ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  extra_deps = [ ":files_metadata_entry_module" ]
+}
+
 js_library("files_password_dialog") {
   deps = [
     "//ui/file_manager/file_manager/common/js:async_util",
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html
index c97a394..f1993d3 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html
+++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html
@@ -95,6 +95,5 @@
       </div>
     </div>
   </template>
-
   <script src="files_metadata_box.js"></script>
 </dom-module>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.js b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.js
index e74f9ffb..6096d482 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-const FilesMetadataBox = Polymer({
+Polymer({
   is: 'files-metadata-box',
 
   properties: {
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html
index fc60dec..4193cb1c 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html
+++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html
@@ -89,6 +89,5 @@
       </div>
     </div>
   </template>
-
   <script src="files_metadata_entry.js"></script>
 </dom-module>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.js b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.js
index 36eeb19..35fbf31a 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-const FilesMetadataEntry = Polymer({
+Polymer({
   is: 'files-metadata-entry',
 
   properties: {
@@ -28,16 +28,6 @@
       type: Boolean,
       value: false,
     },
-
-    /**
-     * True if files-ng is enabled.
-     * @const @type {boolean}
-     * @private
-     */
-    filesNg_: {
-      type: Boolean,
-      value: util.isFilesNg(),
-    }
   },
 
   /**
@@ -45,9 +35,7 @@
    * specific CSS styling.
    */
   created: function() {
-    if (this.filesNg_) {
-      this.setAttribute('files-ng', '');
-    }
+    this.setAttribute('files-ng', '');
   },
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
index fb0c0df..e668aca 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
@@ -139,7 +139,7 @@
   },
 
   /**
-   * @return {!FilesMetadataBox}
+   * @return {!FilesMetadataBoxElement}
    */
   getFilesMetadataBox: function() {
     return this.$['metadata-box'];
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index abd0348..5bc96c1 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -1226,6 +1226,19 @@
       case chrome.fileManagerPrivate.CrostiniEventType.DISABLE:
         this.crostini_.setEnabled(event.vmName, false);
         return this.crostiniController_.redraw();
+
+      // Event is sent when a user drops an unshared file on Plugin VM.
+      // We show the move dialog so the user can move the file or share the
+      // directory.
+      case chrome.fileManagerPrivate.CrostiniEventType
+          .DROP_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED:
+        if (this.ui_.dragInProcess) {
+          FileTasks.showPluginVmMoveDialog(
+              this.selectionHandler.selection.entries, this.volumeManager_,
+              assert(this.ui_), 'Windows', this.fileTransferController_,
+              assert(this.directoryModel_));
+        }
+        break;
     }
   }
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index 1dc3328..d41007c 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -482,6 +482,60 @@
   }
 
   /**
+   * @param {!Entry} entry
+   * @param {!VolumeManager} volumeManager
+   * @return {boolean} True if the entry is from MyFiles.
+   */
+  static isMyFilesEntry(entry, volumeManager) {
+    const location = volumeManager.getLocationInfo(entry);
+    return !!location &&
+        location.rootType === VolumeManagerCommon.RootType.DOWNLOADS;
+  }
+
+  /**
+   * @param {!Array<!Entry>} entries Selected entries to be moved or copied.
+   * @param {!VolumeManager} volumeManager
+   * @param {!FileManagerUI} ui FileManager UI to show dialog.
+   * @param {string} title Dialog title.
+   * @param {?FileTransferController} fileTransferController
+   * @param {!DirectoryModel} directoryModel
+   */
+  static showPluginVmMoveDialog(
+      entries, volumeManager, ui, title, fileTransferController,
+      directoryModel) {
+    if (entries.length == 0) {
+      return;
+    }
+    const isMyFiles = FileTasks.isMyFilesEntry(entries[0], volumeManager);
+    const [messageId, buttonId, toMove] = isMyFiles ?
+        [
+          'UNABLE_TO_OPEN_WITH_PLUGIN_VM_DIRECTORY_NOT_SHARED_MESSAGE',
+          'CONFIRM_MOVE_BUTTON_LABEL',
+          true,
+        ] :
+        [
+          'UNABLE_TO_OPEN_WITH_PLUGIN_VM_EXTERNAL_DRIVE_MESSAGE',
+          'CONFIRM_COPY_BUTTON_LABEL',
+          false,
+        ];
+    const dialog = new FilesConfirmDialog(ui.element);
+    dialog.setOkLabel(strf(buttonId));
+    dialog.show(strf(messageId, title), async () => {
+      if (!fileTransferController) {
+        console.error('FileTransferController not set');
+        return;
+      }
+
+      const pvmDir = await FileTasks.getPvmSharedDir_(volumeManager);
+
+      fileTransferController.executePaste(new FileTransferController.PastePlan(
+          entries.map(e => e.toURL()), [], pvmDir,
+          assert(volumeManager.getLocationInfo(pvmDir)), toMove));
+      directoryModel.changeDirectoryEntry(pvmDir);
+    });
+  }
+
+  /**
    * Executes default task.
    *
    * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the
@@ -666,38 +720,10 @@
             }
           });
           break;
-        case taskResult.FAILED_PLUGIN_VM_TASK_DIRECTORY_NOT_SHARED:
-        case taskResult.FAILED_PLUGIN_VM_TASK_EXTERNAL_DRIVE:
-          const [messageId, buttonId, toMove] =
-              result == taskResult.FAILED_PLUGIN_VM_TASK_DIRECTORY_NOT_SHARED ?
-              [
-                'UNABLE_TO_OPEN_WITH_PLUGIN_VM_DIRECTORY_NOT_SHARED_MESSAGE',
-                'CONFIRM_MOVE_BUTTON_LABEL',
-                true,
-              ] :
-              [
-                'UNABLE_TO_OPEN_WITH_PLUGIN_VM_EXTERNAL_DRIVE_MESSAGE',
-                'CONFIRM_COPY_BUTTON_LABEL',
-                false,
-              ];
-          const dialog = new FilesConfirmDialog(this.ui_.element);
-          dialog.setOkLabel(strf(buttonId));
-          dialog.show(
-              strf(messageId, task.title), async () => {
-                if (!this.fileTransferController_) {
-                  console.error('FileTransferController not set');
-                  return;
-                }
-
-                const pvmDir = await this.getPvmSharedDir_();
-
-                this.fileTransferController_.executePaste(
-                    new FileTransferController.PastePlan(
-                        this.entries_.map(e => e.toURL()), [], pvmDir,
-                        assert(this.volumeManager_.getLocationInfo(pvmDir)),
-                        toMove));
-                this.directoryModel_.changeDirectoryEntry(pvmDir);
-              });
+        case taskResult.FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED:
+          FileTasks.showPluginVmMoveDialog(
+              this.entries_, this.volumeManager_, this.ui_, task.title,
+              this.fileTransferController_, this.directoryModel_);
           break;
       }
     };
@@ -1280,9 +1306,12 @@
     return null;
   }
 
-  async getPvmSharedDir_() {
+  /**
+   * @param {!VolumeManager} volumeManager
+   */
+  static async getPvmSharedDir_(volumeManager) {
     return new Promise((resolve, reject) => {
-      this.volumeManager_
+      volumeManager
           .getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DOWNLOADS)
           .fileSystem.root.getDirectory(
               'PvmDefault', {create: false},
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
index 615549f..66e8a5c9 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
@@ -122,8 +122,7 @@
       },
       TaskResult: {
         MESSAGE_SENT: 'test_ms_task',
-        FAILED_PLUGIN_VM_TASK_DIRECTORY_NOT_SHARED: 'test_fpvtdns_task',
-        FAILED_PLUGIN_VM_TASK_EXTERNAL_DRIVE: 'test_fpvted_task',
+        FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED: 'test_fpvdns_task',
       },
       getFileTasks: function(entries, callback) {
         setTimeout(callback.bind(null, [mockTask]), 0);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js b/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
index 897de21..52b8f94 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
@@ -28,7 +28,7 @@
     this.quickViewModel_ = quickViewModel;
 
     /**
-     * @type {FilesMetadataBox} metadataBox
+     * @type {FilesMetadataBoxElement} metadataBox
      * @private
      */
     this.metadataBox_ = null;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
index 80e8095e..abe9994 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -413,6 +413,16 @@
         e.stopPropagation();
       });
     }
+
+    /**
+     * True while FilesApp is in the process of a drag and drop. Set to true on
+     * 'dragstart', set to false on 'dragend'. If CrostiniEvent
+     * 'drop_failed_plugin_vm_directory_not_shared' is received during drag, we
+     * show the move-to-windows-files dialog.
+     *
+     * @public {boolean}
+     */
+    this.dragInProcess = false;
   }
 
   /**
@@ -486,6 +496,13 @@
         }
       });
     });
+
+    document.addEventListener('dragstart', () => {
+      this.dragInProcess = true;
+    });
+    document.addEventListener('dragend', () => {
+      this.dragInProcess = false;
+    });
   }
 
   /**
diff --git a/ui/file_manager/image_loader/piex_loader.js b/ui/file_manager/image_loader/piex_loader.js
index e344f08..7eeab882 100644
--- a/ui/file_manager/image_loader/piex_loader.js
+++ b/ui/file_manager/image_loader/piex_loader.js
@@ -631,7 +631,7 @@
  * the caller should initiate failure recovery steps.
  *
  * @param {!ArrayBuffer|!File|string} source
- * @param {function()} onPiexModuleFailed
+ * @param {!function()} onPiexModuleFailed
  * @return {!Promise<!PiexLoaderResponse>}
  */
 PiexLoader.load = function(source, onPiexModuleFailed) {
diff --git a/ui/file_manager/integration_tests/file_manager/crostini.js b/ui/file_manager/integration_tests/file_manager/crostini.js
index 8a86123..87d1b75 100644
--- a/ui/file_manager/integration_tests/file_manager/crostini.js
+++ b/ui/file_manager/integration_tests/file_manager/crostini.js
@@ -123,7 +123,7 @@
   ]);
   await remoteCall.waitUntilTaskExecutes(
       appId, 'plugin-vm-app-id|pluginvm|open-with',
-      ['failed_plugin_vm_task_directory_not_shared']);
+      ['failed_plugin_vm_directory_not_shared']);
   await remoteCall.waitForElement(
       appId, '.cr-dialog-frame:not(#default-task-dialog):not([hidden])');
 
@@ -146,7 +146,8 @@
 };
 
 testcase.pluginVmFileOnExternalDriveErrorDialog = async () => {
-  const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS);
+  // Use files outside of MyFiles to show 'copy' rather than 'move'.
+  const appId = await setupAndWaitUntilReady(RootPath.DRIVE);
 
   // Override the tasks so the "Open with Plugin VM App" button becomes a
   // dropdown option.
@@ -189,7 +190,7 @@
   ]);
   await remoteCall.waitUntilTaskExecutes(
       appId, 'plugin-vm-app-id|pluginvm|open-with',
-      ['failed_plugin_vm_task_external_drive']);
+      ['failed_plugin_vm_directory_not_shared']);
   await remoteCall.waitForElement(
       appId, '.cr-dialog-frame:not(#default-task-dialog):not([hidden])');
 
@@ -210,3 +211,26 @@
   // TODO(crbug.com/1049453): Test file is moved. This can only be tested when
   // tests allow creating /MyFiles/PvmDefault.
 };
+
+/**
+ * Tests that when drag from Files app and dropping in the Plugin VM a
+ * dialog is displayed if the containing folder isn't shared with Plugin VM.
+ */
+testcase.pluginVmFileDropFailErrorDialog = async () => {
+  const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS);
+
+  // Select 'hello.txt' file.
+  await remoteCall.callRemoteTestUtil(
+      'fakeMouseClick', appId, ['[id^="listitem-"][file-name="hello.txt"]']);
+
+  // Send 'dragstart'.
+  chrome.test.assertTrue(await remoteCall.callRemoteTestUtil(
+      'fakeEvent', appId, ['body', 'dragstart', {bubbles: true}]));
+
+  // Send CrostiniEvent 'drop_failed_plugin_vm_directory_not_shared'.
+  await sendTestMessage({name: 'onDropFailedPluginVmDirectoryNotShared'});
+
+  // Wait for error dialog.
+  await remoteCall.waitForElement(
+      appId, '.cr-dialog-frame:not(#default-task-dialog):not([hidden])');
+};
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index 2ebd95f..62812ad 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -89,6 +89,8 @@
   explicit PreEventDispatchHandler(View* owner) : owner_(owner) {
     owner_->AddPreTargetHandler(this);
   }
+  PreEventDispatchHandler(const PreEventDispatchHandler&) = delete;
+  PreEventDispatchHandler& operator=(const PreEventDispatchHandler&) = delete;
   ~PreEventDispatchHandler() override { owner_->RemovePreTargetHandler(this); }
 
  private:
@@ -122,8 +124,6 @@
   }
 
   View* owner_;
-
-  DISALLOW_COPY_AND_ASSIGN(PreEventDispatchHandler);
 };
 
 // This event handler receives events in the post-target phase and takes care of
@@ -133,6 +133,8 @@
  public:
   PostEventDispatchHandler()
       : touch_dnd_enabled_(::switches::IsTouchDragDropEnabled()) {}
+  PostEventDispatchHandler(const PostEventDispatchHandler&) = delete;
+  PostEventDispatchHandler& operator=(const PostEventDispatchHandler&) = delete;
   ~PostEventDispatchHandler() override = default;
 
  private:
@@ -168,8 +170,6 @@
   }
 
   bool touch_dnd_enabled_;
-
-  DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -179,22 +179,10 @@
 
 RootView::RootView(Widget* widget)
     : widget_(widget),
-      mouse_pressed_handler_(nullptr),
-      mouse_move_handler_(nullptr),
-      last_click_handler_(nullptr),
-      explicit_mouse_handler_(false),
-      last_mouse_event_flags_(0),
-      last_mouse_event_x_(-1),
-      last_mouse_event_y_(-1),
-      gesture_handler_(nullptr),
-      gesture_handler_set_before_processing_(false),
-      pre_dispatch_handler_(new internal::PreEventDispatchHandler(this)),
-      post_dispatch_handler_(new internal::PostEventDispatchHandler),
-      focus_search_(this, false, false),
-      focus_traversable_parent_(nullptr),
-      focus_traversable_parent_view_(nullptr),
-      event_dispatch_target_(nullptr),
-      old_dispatch_target_(nullptr) {
+      pre_dispatch_handler_(
+          std::make_unique<internal::PreEventDispatchHandler>(this)),
+      post_dispatch_handler_(
+          std::make_unique<internal::PostEventDispatchHandler>()) {
   AddPostTargetHandler(post_dispatch_handler_.get());
   SetEventTargeter(
       std::unique_ptr<ViewTargeter>(new RootViewTargeter(this, this)));
diff --git a/ui/views/widget/root_view.h b/ui/views/widget/root_view.h
index c722307..f5613e4 100644
--- a/ui/views/widget/root_view.h
+++ b/ui/views/widget/root_view.h
@@ -58,6 +58,8 @@
 
   // Creation and lifetime -----------------------------------------------------
   explicit RootView(Widget* widget);
+  RootView(const RootView&) = delete;
+  RootView& operator=(const RootView&) = delete;
   ~RootView() override;
 
   // Tree operations -----------------------------------------------------------
@@ -185,26 +187,26 @@
   //                   ViewTargeter / RootViewTargeter.
 
   // The view currently handing down - drag - up
-  View* mouse_pressed_handler_;
+  View* mouse_pressed_handler_ = nullptr;
 
   // The view currently handling enter / exit
-  View* mouse_move_handler_;
+  View* mouse_move_handler_ = nullptr;
 
   // The last view to handle a mouse click, so that we can determine if
   // a double-click lands on the same view as its single-click part.
-  View* last_click_handler_;
+  View* last_click_handler_ = nullptr;
 
   // true if mouse_pressed_handler_ has been explicitly set
-  bool explicit_mouse_handler_;
+  bool explicit_mouse_handler_ = false;
 
   // Last position/flag of a mouse press/drag. Used if capture stops and we need
   // to synthesize a release.
-  int last_mouse_event_flags_;
-  int last_mouse_event_x_;
-  int last_mouse_event_y_;
+  int last_mouse_event_flags_ = 0;
+  int last_mouse_event_x_ = -1;
+  int last_mouse_event_y_ = -1;
 
   // The View currently handling gesture events.
-  View* gesture_handler_;
+  View* gesture_handler_ = nullptr;
 
   // Used to indicate if the |gesture_handler_| member was set prior to the
   // processing of the current event (i.e., if |gesture_handler_| was set
@@ -212,7 +214,7 @@
   // TODO(tdanderson): It may be possible to eliminate the need for this
   //                   member if |event_dispatch_target_| can be used in
   //                   its place.
-  bool gesture_handler_set_before_processing_;
+  bool gesture_handler_set_before_processing_ = false;
 
   std::unique_ptr<internal::PreEventDispatchHandler> pre_dispatch_handler_;
   std::unique_ptr<internal::PostEventDispatchHandler> post_dispatch_handler_;
@@ -220,20 +222,20 @@
   // Focus ---------------------------------------------------------------------
 
   // The focus search algorithm.
-  FocusSearch focus_search_;
+  FocusSearch focus_search_{this, false, false};
 
   // Whether this root view belongs to the current active window.
   // bool activated_;
 
   // The parent FocusTraversable, used for focus traversal.
-  FocusTraversable* focus_traversable_parent_;
+  FocusTraversable* focus_traversable_parent_ = nullptr;
 
   // The View that contains this RootView. This is used when we have RootView
   // wrapped inside native components, and is used for the focus traversal.
-  View* focus_traversable_parent_view_;
+  View* focus_traversable_parent_view_ = nullptr;
 
-  View* event_dispatch_target_;
-  View* old_dispatch_target_;
+  View* event_dispatch_target_ = nullptr;
+  View* old_dispatch_target_ = nullptr;
 
   // Drag and drop -------------------------------------------------------------
 
@@ -245,8 +247,6 @@
   // Hidden view used to make announcements to the screen reader via an alert or
   // live region update.
   AnnounceTextView* announce_view_ = nullptr;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(RootView);
 };
 
 }  // namespace internal
diff --git a/ui/views/window/non_client_view.h b/ui/views/window/non_client_view.h
index b8df6d4..8b5c2e60 100644
--- a/ui/views/window/non_client_view.h
+++ b/ui/views/window/non_client_view.h
@@ -40,6 +40,8 @@
   };
 
   NonClientFrameView();
+  NonClientFrameView(const NonClientFrameView&) = delete;
+  NonClientFrameView& operator=(const NonClientFrameView&) = delete;
   ~NonClientFrameView() override;
 
   // Used to determine if the frame should be painted as active. Keyed off the
@@ -110,8 +112,6 @@
   // offset into the caption area; the caller will take care of this.
   virtual int GetSystemMenuY() const;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(NonClientFrameView);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -155,6 +155,8 @@
   METADATA_HEADER(NonClientView);
 
   explicit NonClientView(ClientView* client_view);
+  NonClientView(const NonClientView&) = delete;
+  NonClientView& operator=(const NonClientView&) = delete;
   ~NonClientView() override;
 
   // Returns the current NonClientFrameView instance, or NULL if
@@ -245,8 +247,6 @@
 
   // The accessible name of this view.
   base::string16 accessible_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(NonClientView);
 };
 
 }  // namespace views
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index af99fdd..8e28d9f 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -813,7 +813,7 @@
     "grit/weblayer_resources.h",
     "weblayer_resources.pak",
   ]
-  deps = [ "//weblayer/browser/webui:mojo_bindings_js" ]
+  deps = [ "//weblayer/browser/webui:mojo_bindings_webui_js" ]
 }
 # TODO(jam): move weblayer_shell_resources_grit and copy_shell_resources here in
 # a way that's shareable?
diff --git a/weblayer/browser/resources/weblayer_internals/weblayer_internals.html b/weblayer/browser/resources/weblayer_internals/weblayer_internals.html
index 8c10a03..0d23f12 100644
--- a/weblayer/browser/resources/weblayer_internals/weblayer_internals.html
+++ b/weblayer/browser/resources/weblayer_internals/weblayer_internals.html
@@ -4,14 +4,7 @@
     <meta charset="utf-8">
     <title>WebLayer Internals</title>
     <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
-
-    <script src="chrome://resources/js/cr.js"></script>
-    <script src="chrome://resources/js/assert.js"></script>
-    <script src="chrome://resources/js/promise_resolver.js"></script>
-    <script src="chrome://resources/js/util.js"></script>
-    <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
-    <script src="weblayer_internals.mojom-lite.js"></script>
-    <script src="weblayer_internals.js"></script>
+    <script type="module" src="weblayer_internals.js"></script>
   </head>
   <body>
     <h1>WebLayer Internals</h1>
diff --git a/weblayer/browser/resources/weblayer_internals/weblayer_internals.js b/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
index e742ba2..bdd1de94 100644
--- a/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
+++ b/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
@@ -2,26 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
 /* Javascript module for chrome://weblayer. */
-(function() {
+
+import {isAndroid} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
+import {PageHandler} from './weblayer_internals.mojom-webui.js';
 
 /* Main entry point. */
-document.addEventListener('DOMContentLoaded', function() {
+window.document.addEventListener('DOMContentLoaded', async function() {
   // Setup backend mojo.
-  const pageHandler = weblayerInternals.mojom.PageHandler.getRemote();
-  if (cr.isAndroid) {
-    pageHandler.getRemoteDebuggingEnabled().then((response) => {
-        let checkbox = $('remote-debug');
-        checkbox.checked = response.enabled;
-        checkbox.addEventListener('click', (event) => {
-          pageHandler.setRemoteDebuggingEnabled(event.target.checked);
-        });
-
-        $('remote-debug-label').removeAttribute('hidden');
+  const pageHandler = PageHandler.getRemote();
+  if (isAndroid) {
+    const {enabled} = await pageHandler.getRemoteDebuggingEnabled();
+    const checkbox = $('remote-debug');
+    checkbox.checked = enabled;
+    checkbox.addEventListener('click', (event) => {
+      pageHandler.setRemoteDebuggingEnabled(event.target.checked);
     });
+
+    $('remote-debug-label').removeAttribute('hidden');
   }
 });
-
-}());
diff --git a/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.cc b/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.cc
index 4eb32a4f71..f89f95f 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.cc
+++ b/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.cc
@@ -14,18 +14,6 @@
 
 namespace weblayer {
 
-// static
-void SafeBrowsingSubresourceHelper::CreateForWebContents(
-    content::WebContents* web_contents,
-    SafeBrowsingUIManager* ui_manager) {
-  if (FromWebContents(web_contents))
-    return;
-
-  web_contents->SetUserData(UserDataKey(),
-                            base::WrapUnique(new SafeBrowsingSubresourceHelper(
-                                web_contents, ui_manager)));
-}
-
 SafeBrowsingSubresourceHelper::~SafeBrowsingSubresourceHelper() = default;
 
 void SafeBrowsingSubresourceHelper::ReadyToCommitNavigation(
diff --git a/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.h b/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.h
index 0cb15d7..08b6a36 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.h
+++ b/weblayer/browser/safe_browsing/safe_browsing_subresource_helper.h
@@ -25,9 +25,6 @@
  public:
   ~SafeBrowsingSubresourceHelper() override;
 
-  static void CreateForWebContents(content::WebContents* web_contents,
-                                   SafeBrowsingUIManager* ui_manager);
-
   // WebContentsObserver::
   void ReadyToCommitNavigation(
       content::NavigationHandle* navigation_handle) override;
diff --git a/weblayer/browser/webui/BUILD.gn b/weblayer/browser/webui/BUILD.gn
index e9c9ce3..9031991 100644
--- a/weblayer/browser/webui/BUILD.gn
+++ b/weblayer/browser/webui/BUILD.gn
@@ -6,4 +6,5 @@
 
 mojom("mojo_bindings") {
   sources = [ "weblayer_internals.mojom" ]
+  webui_module_path = "/"
 }
diff --git a/weblayer/browser/webui/weblayer_internals_ui.cc b/weblayer/browser/webui/weblayer_internals_ui.cc
index d136188..471ab781 100644
--- a/weblayer/browser/webui/weblayer_internals_ui.cc
+++ b/weblayer/browser/webui/weblayer_internals_ui.cc
@@ -18,7 +18,7 @@
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(kChromeUIWebLayerHost);
   source->AddResourcePath("weblayer_internals.js", IDR_WEBLAYER_INTERNALS_JS);
-  source->AddResourcePath("weblayer_internals.mojom-lite.js",
+  source->AddResourcePath("weblayer_internals.mojom-webui.js",
                           IDR_WEBLAYER_INTERNALS_MOJO_JS);
   source->SetDefaultResource(IDR_WEBLAYER_INTERNALS_HTML);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
diff --git a/weblayer/weblayer_resources.grd b/weblayer/weblayer_resources.grd
index 5bcd087..755f5af 100644
--- a/weblayer/weblayer_resources.grd
+++ b/weblayer/weblayer_resources.grd
@@ -11,7 +11,7 @@
     <includes>
       <include name="IDR_WEBLAYER_INTERNALS_HTML" file="browser/resources/weblayer_internals/weblayer_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_WEBLAYER_INTERNALS_JS" file="browser/resources/weblayer_internals/weblayer_internals.js" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_WEBLAYER_INTERNALS_MOJO_JS" file="${root_gen_dir}/weblayer/browser/webui/weblayer_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" />
+      <include name="IDR_WEBLAYER_INTERNALS_MOJO_JS" file="${root_gen_dir}/mojom-webui/weblayer/browser/webui/weblayer_internals.mojom-webui.js" use_base_dir="false" type="BINDATA" />
       <include name="IDR_SUBRESOURCE_FILTER_UNINDEXED_RULESET" file="../third_party/subresource-filter-ruleset/data/UnindexedRules" type="BINDATA" compress="brotli" />
       <include name="IDR_SUBRESOURCE_FILTER_UNINDEXED_RULESET_MANIFEST_JSON" file="../third_party/subresource-filter-ruleset/manifest.json" type="BINDATA" />
     </includes>